This code sets out how to upload and then analyse Whatsapp text data using both charts and networks.

library("RCurl")
Loading required package: bitops

Attaching package: <U+393C><U+3E31>RCurl<U+393C><U+3E32>

The following object is masked from <U+393C><U+3E31>package:tidyr<U+393C><U+3E32>:

    complete
library("data.table")
data.table 1.10.4
  The fastest way to learn (by data.table authors): https://www.datacamp.com/courses/data-analysis-the-data-table-way
  Documentation: ?data.table, example(data.table) and browseVignettes("data.table")
  Release notes, videos and slides: http://r-datatable.com

Attaching package: <U+393C><U+3E31>data.table<U+393C><U+3E32>

The following objects are masked from <U+393C><U+3E31>package:reshape2<U+393C><U+3E32>:

    dcast, melt

The following objects are masked from <U+393C><U+3E31>package:dplyr<U+393C><U+3E32>:

    between, first, last

The following object is masked from <U+393C><U+3E31>package:purrr<U+393C><U+3E32>:

    transpose
library(stringr)
#tab = read.delim(getURL("https://raw.githubusercontent.com/robert-sturrock/whatsapp-analysis/master/chat.txt"))
#write.table(tab, file="text.csv",sep=",",col.names=FALSE,row.names=FALSE)
chat <- read.table("C:/Users/rober/Desktop/chat.txt",  fill=TRUE, quote="", sep="\n", encoding="UTF-8")
names(chat) <- "string"

Now we need to look at the data and format it approperiately

head(chat)

So we can see we have a date, time, sender, and message.

The first obvious issue here is that one of the senders names has been messed up. We can fix this using the regex commands in R

chat$string <- gsub("1 (215) .*: ", "Debbie Blair: ", chat$string )
head(chat$string)
[1] "<U+FEFF>7/22/16, 6:47:12 PM: <U+200E><U+202A>+1 (215) 941-2128<U+202C> created group “We need a good name”"                                                                                 
[2] "7/22/16, 6:47:12 PM: <U+200E><U+202A>+1 (215) 941-2128<U+202C> added you"                                                                                                           
[3] "7/22/16, 6:47:20 PM: <U+202A>+1 (215) 941-2128<U+202C>: Hi everyone \xf0\u009f\u0099\u008c\xf0\u009f\u0099\u008c\xf0\u009f\u0099\u008c"                                     
[4] "7/22/16, 6:55:06 PM: Elizabeth Stone: Lili/Isabel - what was your gut reaction? Do you think we should go for it?"                                          
[5] "7/22/16, 6:57:31 PM: Isabel Lachenauer: I didn't see it. I arrived at the pub 10 mins late bc I am a slow walker and by then lili and the landlord had gone"
[6] "7/22/16, 6:57:41 PM: Isabel Lachenauer: But the neighborhood is CUTE AF"                                                                                    

Now that we have made that correction we need to split the string of text into the individual components identified above:

library(tidyverse)
regx <- "(\\d+/\\d+/\\d+),\\s+(\\d+:\\d+:\\d+ [A|P]M):\\s+(\\w+\\s*\\w+):\\s+(.*)"
tmp <- chat %>% 
    tidyr::extract(string, c("date", "time", "sender", "message"), regx, remove=FALSE)
#eliminate NA rows (for now)
tmp <- tmp[complete.cases(tmp)]
Error in `[.data.frame`(tmp, complete.cases(tmp)) : 
  undefined columns selected

We now have our desired variables. Lets build some basic functionality like search

#regular expression search
grep("sex", tmp$message, value=TRUE)
 [1] "So many cool seeming women suddenly getting so weird about praying rosaries and no sex before marriage"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
 [2] "Guys don't sext in the group chat"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
 [3] "And a 1w9 (sexual variant) from the second"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
 [4] "The election of Donald Trump as President of the United States of America has sent a signal out to the World that not only is it OK to BE xenophobic, homophobic, misogynistic and racist, that not only is it OK to deal with those who exercise their right to object to what you have to say by punching them in the face, that not only is it OK to sexually assault women, but now you can PROUDLY PROCLAIM your hatred of other races, your distrust for persons who are not like you, your admiration for political despots and dictators and your sexual exploitation of women AND be rewarded for it. And that’s what scares me to the very core. "
 [5] "i am going to a unisex barber on Sat"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
 [6] "Can we do a problem solving round/ creativity round ?? Like make lizzie come up with a 60sex pitch for a campaign"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
 [7] "and u can be friends with all members of all sexes/genders"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
 [8] "Just worse than expected n I definitely need operation again. The non absorAble mesh didn't work. My small intestine and small bowel and rectum are all not in their right place. So I need a permanent mesh and another operation. Permanent mesh also means sex will be painful and prob cause complications if I ever want to have kids ( at least I don't have periods and prob never will so maybe not too relevant... 😣)"                                                                                                                                                                                                                            
 [9] "Is it just all old ppl talking about their sex/dating ?"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
[10] "They want sex basically"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
[11] "i make inappropriate sex jokes"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
[12] "AJ is stuck in Essex and not allowed to drive back to London"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
[13] "So he thinks its cos of condensation build up (you guys must be having sweaty sex) mainly cos teh cupboard there prob blocked air flow - so he wud suggest not putting the cupboard back there. he also reiterated the leave a window open upstairs/downstairs when out for the day which i guess we cud start doing and rotate whose window it is"                                                                                                                                                                                                                                                                                                           
[14] "u guys can have sex in my room"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
[15] "And sex tilll like 12.30 so no wonder you are tired"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
[16] "and you were having sex"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
[17] "Like if she didn't stalk him and just wanted some decent sex, I would say def invite to summer party"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
[18] "Not ideal for being a chill hook up/sex"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
[19] "I think if she asked him and he said yes they will end up having sex"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
[20] "Is this some sexy thing u guys are planning"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
[21] "That's good it's for sexual harassment too"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
[22] "Only just realised that the chorus is a call back to I'm too sexy for my shirt"                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
#function that returns other columns of the data as well
text_search <- function(text, df){
  tmp <- df
  tmp_index <- grep(text, tmp$message)
  tmp[c(tmp_index),c("sender", "message")]
}
text_search("sex", tmp)
#function to search around a specific instance (message before and after)
# this function generates another function that allows the user to select which instance of a word, and the 
# number of lines around that word, they want to see. 
conv_search <- function(text, df){ 
  tmp <- df
  tmp_index <- grep(text, tmp$message)
  
  #return lines
  index <- tmp_index
  
  function(instance, num_lines){
    if (num_lines %% 2 !=0){"error, needs even number"} else {
    
    instance <- index[instance]
    start <- instance - num_lines/2
    end   <- instance + num_lines/2  
    tmp[start:end, c("sender", "message")]
    } 
  }
  
  
}
sex_search <- conv_search("sex", tmp)
sex_search(2,6)
library(wordcloud)
Loading required package: RColorBrewer

Great. So we built some functions that make it easy to search text.

But searching isn’t really the best way to get data about what people talked about. Charts on the other hand are awesome.

I start by building a simple frequency chart of how often a given work was said

# Create a single block of text with all the words
test <- unlist(tmp$message[tmp$sender == "Liam Kirwin"])
test <- unlist(tmp$message)
test <- paste(test, sep="",collapse =" ")
# load required packages
library(tm)
Loading required package: NLP

Attaching package: <U+393C><U+3E31>NLP<U+393C><U+3E32>

The following object is masked from <U+393C><U+3E31>package:ggplot2<U+393C><U+3E32>:

    annotate
library(dplyr)
library(xtable)
docs <- Corpus(VectorSource(test)) %>%
  tm_map(removePunctuation) %>%
  tm_map(removeNumbers) %>%
  tm_map(tolower)  %>%
  tm_map(removeWords, stopwords("english")) %>%
  tm_map(stripWhitespace) %>%
  tm_map(PlainTextDocument)
tdm <- TermDocumentMatrix(docs) %>%
  as.matrix()
tdm <- as.matrix(tdm[,1])
tdm <- as.matrix(tdm[order(tdm, decreasing = TRUE),])
#tdm <- as.matrix(tdm[10:17546,])
#tdm <- tdm[order(tdm, decreasing = TRUE),]
wordcloud(row.names(tdm), tdm, min.freq = 35, scale=c(5, .2), random.order = FALSE, random.color = FALSE, colors= c("indianred1","indianred2","indianred3","indianred"))

#Now we create a wordcloud function 
WA_wordcloud <- function(sender, df, min.freq){
  
  #required packages
  #require(tm)
  #require(dplyr)
  #require(xtable)
  #require(wordcloud)
  #require(stringr)
  
  #set function
  tmp <- unlist(df$message[df$sender == sender])
  tmp <- paste(tmp, sep="",collapse ="")
  
  #eliminate all non alpha numberic
  tmp <- str_replace_all(tmp, "[^a-zA-Z0-9]"," ")
  
  #create term document matrix and format it
  tmp_docs <- Corpus(VectorSource(tmp)) %>%
  tm_map(removePunctuation) %>%
  tm_map(removeNumbers) %>%
  tm_map(tolower)  %>%
  tm_map(removeWords, stopwords("english")) %>%
  tm_map(removeWords,"image") %>%
  tm_map(stripWhitespace) %>%
  tm_map(PlainTextDocument)
  
  tmp_tdm <- TermDocumentMatrix(tmp_docs) %>%
  as.matrix()
  
  tmp_tdm <- as.matrix(tmp_tdm[,1])
  tmp_tdm <- as.matrix(tmp_tdm[order(tmp_tdm, decreasing = TRUE),])
  
  #create wordcloud
  layout(matrix(c(1,2), nrow = 2), heights = c(1,2))
  par(mar = rep(0,4))
  plot.new()
  text(x=0.5, y=0.5, sender)
  
  
  wordcloud(row.names(tmp_tdm), tmp_tdm, 
            min.freq = min.freq, 
            scale=c(2, .1), 
            random.order = FALSE, 
            random.color = FALSE,  
            colors= c("indianred1","indianred2","indianred3","indianred"))
  
}
WA_wordcloud(sender = "Liam Kirwin", df = tmp, min.freq = 15)

flat_names <- list("Liam Kirwin", "Isabel Lachenauer", "Robert", "Debbie Blair", "Elizabeth Stone")
lapply(flat_names, function(x) WA_wordcloud(x, df = tmp, min.freq = 25))

[[1]]
NULL

[[2]]
NULL

[[3]]
NULL

[[4]]
NULL

[[5]]
NULL

Another potentially interesting idea is to do a wordcloud of words that people use more than the average. This would involve calculating two data.frames/matricies with words and frequencies. And then subtracting the individual words from the average.

Step 1:

#create a function that creates a tdm 
tdm_creator <- function(sender="all", df){
  
  #set function
  if(sender != "all"){tmp <- unlist(df$message[df$sender == sender])} else {tmp <- unlist(df$message)}
  tmp <- paste(tmp, sep="",collapse ="")
  
  #eliminate all non alpha numberic
  tmp <- str_replace_all(tmp, "[^a-zA-Z0-9]"," ")
  
  #create term document matrix and format it
  tmp_docs <- Corpus(VectorSource(tmp)) %>%
  tm_map(removePunctuation) %>%
  tm_map(removeNumbers) %>%
  tm_map(tolower)  %>%
  tm_map(removeWords, stopwords("english")) %>%
  tm_map(removeWords,"image") %>%
  tm_map(stripWhitespace) %>%
  tm_map(PlainTextDocument)
  
  tmp_tdm <- TermDocumentMatrix(tmp_docs) %>%
  as.matrix()
  
  tmp_tdm <- as.matrix(tmp_tdm[,1])
  as.matrix(tmp_tdm[order(tmp_tdm, decreasing = TRUE),])
}
word_df <- function(matr){
  data.frame(word = row.names(matr), freq = matr)
}
#create data.frames to compare
isabel <- tdm_creator(sender = "Isabel Lachenauer", df = tmp)
liam <- tdm_creator(sender = "Liam Kirwin", df = tmp)
all <- tdm_creator(df = tmp)
isabel <- word_df(isabel)
liam <- word_df(liam)
all <- word_df(all)
t <- left_join(liam, all, by = "word")
Column `word` joining factors with different levels, coercing to character vector
t <- left_join(isabel, all, by = "word")
Column `word` joining factors with different levels, coercing to character vector
#identify words that liam says relatively more than others
t$diff <- t$freq.x - t$freq.y/5
t %>% arrange(desc(diff)) %>% head()
#control also for frequency that the word appears in the general group chat 
t <- t[t$freq.x <= t$freq.y,]
t$diff2 <- (t$freq.x - t$freq.y/5)/t$freq.y
t %>% arrange(desc(diff2)) %>% head()
#create a word cloud of most unique words
t2 <- t %>% filter(diff>0)
wordcloud(t2$word, t2$diff,
            scale=c(3, .1), 
            random.order = FALSE, 
            random.color = FALSE,  
            colors= c("indianred1","indianred2","indianred3","indianred"))

# use alternative method, but only use words that appear at least 3 times
t3 <- t %>% filter(diff2>0 & freq.x >3)
wordcloud(t3$word, t3$diff2,
            scale=c(3, .1), 
            max.word = 100,
            random.order = FALSE, 
            random.color = FALSE,  
            colors= c("indianred1","indianred2","indianred3","indianred"))

# Function that creates a unique word cloud by person 
unique_wordcloud <- function(df, sender, type){
  
  #total senders
  tot_senders <- length(unique(df$sender))
  
  #create tdm
  person <- word_df(tdm_creator(sender = sender, df = tmp))
  all <- word_df(tdm_creator(df = tmp))
  
  t <- left_join(person, all, by = "word")
  #identify words that liam says relatively more than others
  
  t$diff <- t$freq.x - t$freq.y/tot_senders
  
  #control also for frequency that the word appears in the general group chat 
  
  t <- t[t$freq.x <= t$freq.y,]
  t$diff2 <- (t$freq.x - t$freq.y/tot_senders)/t$freq.y
  
  #create a word cloud of most unique words
  
  t2 <- t %>% filter(diff>0)
  t3 <- t %>% filter(diff2>0 & freq.x >3)
  
  
  if (type == 1){
  wordcloud(t2$word, t2$diff,
              scale=c(3, .1), 
              random.order = FALSE, 
              random.color = FALSE,  
              colors= c("indianred1","indianred2","indianred3","indianred"))} 
  
  else if (type ==2){
  wordcloud(t3$word, t3$diff2,
            scale=c(3, .1), 
            random.order = FALSE, 
            random.color = FALSE,  
            colors= c("indianred1","indianred2","indianred3","indianred"))
  } else {stop('invalid type selected')}
  
    
  
}
unique_wordcloud(df = tmp, sender = "Elizabeth Stone", type = 2)
Column `word` joining factors with different levels, coercing to character vector

unique_wordcloud(df = tmp, sender = "Robert", type = 2)
Column `word` joining factors with different levels, coercing to character vector

flat_names <- list("Liam Kirwin", "Isabel Lachenauer", "Robert", "Debbie Blair", "Elizabeth Stone")
lapply(flat_names, function(x) unique_wordcloud(sender = x, df = tmp, type = 2))
Column `word` joining factors with different levels, coercing to character vector

Column `word` joining factors with different levels, coercing to character vector

Column `word` joining factors with different levels, coercing to character vector

rugby could not be fit on page. It will not be plotted.theyre could not be fit on page. It will not be plotted.anger could not be fit on page. It will not be plotted.beauty could not be fit on page. It will not be plotted.calling could not be fit on page. It will not be plotted.caused could not be fit on page. It will not be plotted.conservative could not be fit on page. It will not be plotted.couldnt could not be fit on page. It will not be plotted.dphil could not be fit on page. It will not be plotted.eleanor could not be fit on page. It will not be plotted.everybody could not be fit on page. It will not be plotted.explained could not be fit on page. It will not be plotted.field could not be fit on page. It will not be plotted.gusy could not be fit on page. It will not be plotted.handy could not be fit on page. It will not be plotted.hasnt could not be fit on page. It will not be plotted.hatred could not be fit on page. It will not be plotted.interest could not be fit on page. It will not be plotted.isabeli could not be fit on page. It will not be plotted.mayb could not be fit on page. It will not be plotted.medical could not be fit on page. It will not be plotted.melbourne could not be fit on page. It will not be plotted.million could not be fit on page. It will not be plotted.monthly could not be fit on page. It will not be plotted.nowbut could not be fit on page. It will not be plotted.nytimes could not be fit on page. It will not be plotted.odeon could not be fit on page. It will not be plotted.operation could not be fit on page. It will not be plotted.pdf could not be fit on page. It will not be plotted.president could not be fit on page. It will not be plotted.prof could not be fit on page. It will not be plotted.pulled could not be fit on page. It will not be plotted.ray could not be fit on page. It will not be plotted.rotate could not be fit on page. It will not be plotted.sam could not be fit on page. It will not be plotted.sara could not be fit on page. It will not be plotted.soi could not be fit on page. It will not be plotted.sorta could not be fit on page. It will not be plotted.steve could not be fit on page. It will not be plotted.tate could not be fit on page. It will not be plotted.useful could not be fit on page. It will not be plotted.version could not be fit on page. It will not be plotted.ways could not be fit on page. It will not be plotted.werent could not be fit on page. It will not be plotted.west could not be fit on page. It will not be plotted.willing could not be fit on page. It will not be plotted.shud could not be fit on page. It will not be plotted.haev could not be fit on page. It will not be plotted.disorder could not be fit on page. It will not be plotted.ifs could not be fit on page. It will not be plotted.morgan could not be fit on page. It will not be plotted.shut could not be fit on page. It will not be plotted.terrible could not be fit on page. It will not be plotted.ityeah could not be fit on page. It will not be plotted.masters could not be fit on page. It will not be plotted.pound could not be fit on page. It will not be plotted.shops could not be fit on page. It will not be plotted.shoudl could not be fit on page. It will not be plotted.suits could not be fit on page. It will not be plotted.thingy could not be fit on page. It will not be plotted.wasnt could not be fit on page. It will not be plotted.woudl could not be fit on page. It will not be plotted.prob could not be fit on page. It will not be plotted.okay could not be fit on page. It will not be plotted.sth could not be fit on page. It will not be plotted.teh could not be fit on page. It will not be plotted.adn could not be fit on page. It will not be plotted.cant could not be fit on page. It will not be plotted.murray could not be fit on page. It will not be plotted.cycle could not be fit on page. It will not be plotted.fracture could not be fit on page. It will not be plotted.fyi could not be fit on page. It will not be plotted.garden could not be fit on page. It will not be plotted.mental could not be fit on page. It will not be plotted.mike could not be fit on page. It will not be plotted.rozalie could not be fit on page. It will not be plotted.rock could not be fit on page. It will not be plotted.stupid could not be fit on page. It will not be plotted.thursday could not be fit on page. It will not be plotted.wouldnt could not be fit on page. It will not be plotted.trump could not be fit on page. It will not be plotted.cos could not be fit on page. It will not be plotted.tho could not be fit on page. It will not be plotted.app could not be fit on page. It will not be plotted.cards could not be fit on page. It will not be plotted.piece could not be fit on page. It will not be plotted.podcast could not be fit on page. It will not be plotted.security could not be fit on page. It will not be plotted.sense could not be fit on page. It will not be plotted.buying could not be fit on page. It will not be plotted.spent could not be fit on page. It will not be plotted.upset could not be fit on page. It will not be plotted.ppl could not be fit on page. It will not be plotted.alice could not be fit on page. It will not be plotted.america could not be fit on page. It will not be plotted.sat could not be fit on page. It will not be plotted.therapy could not be fit on page. It will not be plotted.altho could not be fit on page. It will not be plotted.badoo could not be fit on page. It will not be plotted.beat could not be fit on page. It will not be plotted.brexit could not be fit on page. It will not be plotted.cause could not be fit on page. It will not be plotted.doesnt could not be fit on page. It will not be plotted.human could not be fit on page. It will not be plotted.jsut could not be fit on page. It will not be plotted.listen could not be fit on page. It will not be plotted.mile could not be fit on page. It will not be plotted.minutes could not be fit on page. It will not be plotted.research could not be fit on page. It will not be plotted.states could not be fit on page. It will not be plotted.tbh could not be fit on page. It will not be plotted.therapist could not be fit on page. It will not be plotted.tuesday could not be fit on page. It will not be plotted.black could not be fit on page. It will not be plotted.didnt could not be fit on page. It will not be plotted.wont could not be fit on page. It will not be plotted.account could not be fit on page. It will not be plotted.anniversary could not be fit on page. It will not be plotted.caught could not be fit on page. It will not be plotted.file could not be fit on page. It will not be plotted.herei could not be fit on page. It will not be plotted.homeless could not be fit on page. It will not be plotted.lizziei could not be fit on page. It will not be plotted.media could not be fit on page. It will not be plotted.mphil could not be fit on page. It will not be plotted.opposed could not be fit on page. It will not be plotted.realised could not be fit on page. It will not be plotted.sun could not be fit on page. It will not be plotted.wimbledon could not be fit on page. It will not be plotted.young could not be fit on page. It will not be plotted.dont could not be fit on page. It will not be plotted.assume could not be fit on page. It will not be plotted.bar could not be fit on page. It will not be plotted.lizzie could not be fit on page. It will not be plotted.latest could not be fit on page. It will not be plotted.uber could not be fit on page. It will not be plotted.wall could not be fit on page. It will not be plotted.whats could not be fit on page. It will not be plotted.awesome could not be fit on page. It will not be plotted.die could not be fit on page. It will not be plotted.beautiful could not be fit on page. It will not be plotted.entire could not be fit on page. It will not be plotted.god could not be fit on page. It will not be plotted.org could not be fit on page. It will not be plotted.anxious could not be fit on page. It will not be plotted.bitch could not be fit on page. It will not be plotted.bottom could not be fit on page. It will not be plotted.chance could not be fit on page. It will not be plotted.cry could not be fit on page. It will not be plotted.discussed could not be fit on page. It will not be plotted.earn could not be fit on page. It will not be plotted.economics could not be fit on page. It will not be plotted.everywhere could not be fit on page. It will not be plotted.exit could not be fit on page. It will not be plotted.fellow could not be fit on page. It will not be plotted.fest could not be fit on page. It will not be plotted.festival could not be fit on page. It will not be plotted.gear could not be fit on page. It will not be plotted.killed could not be fit on page. It will not be plotted.model could not be fit on page. It will not be plotted.official could not be fit on page. It will not be plotted.oliver could not be fit on page. It will not be plotted.public could not be fit on page. It will not be plotted.reasonable could not be fit on page. It will not be plotted.relevant could not be fit on page. It will not be plotted.shortwave could not be fit on page. It will not be plotted.solve could not be fit on page. It will not be plotted.taxes could not be fit on page. It will not be plotted.technically could not be fit on page. It will not be plotted.meeting could not be fit on page. It will not be plotted.def could not be fit on page. It will not be plotted.men could not be fit on page. It will not be plotted.tickets could not be fit on page. It will not be plotted.irish could not be fit on page. It will not be plotted.dublin could not be fit on page. It will not be plotted.bike could not be fit on page. It will not be plotted.conference could not be fit on page. It will not be plotted.drinks could not be fit on page. It will not be plotted.leg could not be fit on page. It will not be plotted.white could not be fit on page. It will not be plotted.girl could not be fit on page. It will not be plotted.seems could not be fit on page. It will not be plotted.text could not be fit on page. It will not be plotted.alone could not be fit on page. It will not be plotted.kill could not be fit on page. It will not be plotted.texted could not be fit on page. It will not be plotted.anyway could not be fit on page. It will not be plotted.live could not be fit on page. It will not be plotted.http could not be fit on page. It will not be plotted.body could not be fit on page. It will not be plotted.bianca could not be fit on page. It will not be plotted.dance could not be fit on page. It will not be plotted.drinking could not be fit on page. It will not be plotted.lets could not be fit on page. It will not be plotted.lived could not be fit on page. It will not be plotted.seeing could not be fit on page. It will not be plotted.hospital could not be fit on page. It will not be plotted.labour could not be fit on page. It will not be plotted.ireland could not be fit on page. It will not be plotted.queue could not be fit on page. It will not be plotted.oxford could not be fit on page. It will not be plotted.social could not be fit on page. It will not be plotted.whatever could not be fit on page. It will not be plotted.wanna could not be fit on page. It will not be plotted.lives could not be fit on page. It will not be plotted.record could not be fit on page. It will not be plotted.tons could not be fit on page. It will not be plotted.every could not be fit on page. It will not be plotted.ago could not be fit on page. It will not be plotted.park could not be fit on page. It will not be plotted.worse could not be fit on page. It will not be plotted.appt could not be fit on page. It will not be plotted.clicked could not be fit on page. It will not be plotted.explain could not be fit on page. It will not be plotted.fast could not be fit on page. It will not be plotted.helpful could not be fit on page. It will not be plotted.music could not be fit on page. It will not be plotted.plant could not be fit on page. It will not be plotted.private could not be fit on page. It will not be plotted.pubs could not be fit on page. It will not be plotted.ridiculous could not be fit on page. It will not be plotted.shitty could not be fit on page. It will not be plotted.shower could not be fit on page. It will not be plotted.sold could not be fit on page. It will not be plotted.themi could not be fit on page. It will not be plotted.tooi could not be fit on page. It will not be plotted.twitter could not be fit on page. It will not be plotted.upstairs could not be fit on page. It will not be plotted.least could not be fit on page. It will not be plotted.bridge could not be fit on page. It will not be plotted.health could not be fit on page. It will not be plotted.ive could not be fit on page. It will not be plotted.kept could not be fit on page. It will not be plotted.kinda could not be fit on page. It will not be plotted.loli could not be fit on page. It will not be plotted.paul could not be fit on page. It will not be plotted.plus could not be fit on page. It will not be plotted.sex could not be fit on page. It will not be plotted.tax could not be fit on page. It will not be plotted.theatre could not be fit on page. It will not be plotted.double could not be fit on page. It will not be plotted.emailed could not be fit on page. It will not be plotted.john could not be fit on page. It will not be plotted.man could not be fit on page. It will not be plotted.tim could not be fit on page. It will not be plotted.boyfriend could not be fit on page. It will not be plotted.self could not be fit on page. It will not be plotted.www could not be fit on page. It will not be plotted.group could not be fit on page. It will not be plotted.post could not be fit on page. It will not be plotted.vote could not be fit on page. It will not be plotted.based could not be fit on page. It will not be plotted.figure could not be fit on page. It will not be plotted.barely could not be fit on page. It will not be plotted.exercise could not be fit on page. It will not be plotted.sunny could not be fit on page. It will not be plotted.trust could not be fit on page. It will not be plotted.bus could not be fit on page. It will not be plotted.country could not be fit on page. It will not be plotted.course could not be fit on page. It will not be plotted.except could not be fit on page. It will not be plotted.itand could not be fit on page. It will not be plotted.nights could not be fit on page. It will not be plotted.phd could not be fit on page. It will not be plotted.added could not be fit on page. It will not be plotted.ass could not be fit on page. It will not be plotted.assumed could not be fit on page. It will not be plotted.changed could not be fit on page. It will not be plotted.complete could not be fit on page. It will not be plotted.cover could not be fit on page. It will not be plotted.creepy could not be fit on page. It will not be plotted.december could not be fit on page. It will not be plotted.ends could not be fit on page. It will not be plotted.forever could not be fit on page. It will not be plotted.funi could not be fit on page. It will not be plotted.kids could not be fit on page. It will not be plotted.listened could not be fit on page. It will not be plotted.ooh could not be fit on page. It will not be plotted.plays could not be fit on page. It will not be plotted.productive could not be fit on page. It will not be plotted.promise could not be fit on page. It will not be plotted.ran could not be fit on page. It will not be plotted.random could not be fit on page. It will not be plotted.reasons could not be fit on page. It will not be plotted.serious could not be fit on page. It will not be plotted.shoes could not be fit on page. It will not be plotted.snap could not be fit on page. It will not be plotted.special could not be fit on page. It will not be plotted.suck could not be fit on page. It will not be plotted.washing could not be fit on page. It will not be plotted.weekends could not be fit on page. It will not be plotted.fucking could not be fit on page. It will not be plotted.https could not be fit on page. It will not be plotted.basically could not be fit on page. It will not be plotted.pub could not be fit on page. It will not be plotted.guys could not be fit on page. It will not be plotted.telling could not be fit on page. It will not be plotted.win could not be fit on page. It will not be plotted.sent could not be fit on page. It will not be plotted.wedding could not be fit on page. It will not be plotted.bought could not be fit on page. It will not be plotted.show could not be fit on page. It will not be plotted.walking could not be fit on page. It will not be plotted.tennis could not be fit on page. It will not be plotted.almond could not be fit on page. It will not be plotted.realise could not be fit on page. It will not be plotted.rush could not be fit on page. It will not be plotted.splitwise could not be fit on page. It will not be plotted.surprise could not be fit on page. It will not be plotted.wearing could not be fit on page. It will not be plotted.club could not be fit on page. It will not be plotted.moving could not be fit on page. It will not be plotted.british could not be fit on page. It will not be plotted.charge could not be fit on page. It will not be plotted.court could not be fit on page. It will not be plotted.girls could not be fit on page. It will not be plotted.hint could not be fit on page. It will not be plotted.knows could not be fit on page. It will not be plotted.lucy could not be fit on page. It will not be plotted.mentioned could not be fit on page. It will not be plotted.names could not be fit on page. It will not be plotted.plants could not be fit on page. It will not be plotted.report could not be fit on page. It will not be plotted.response could not be fit on page. It will not be plotted.road could not be fit on page. It will not be plotted.service could not be fit on page. It will not be plotted.shouldn could not be fit on page. It will not be plotted.shows could not be fit on page. It will not be plotted.stand could not be fit on page. It will not be plotted.ten could not be fit on page. It will not be plotted.tie could not be fit on page. It will not be plotted.travel could not be fit on page. It will not be plotted.type could not be fit on page. It will not be plotted.voted could not be fit on page. It will not be plotted.gonna could not be fit on page. It will not be plotted.found could not be fit on page. It will not be plotted.place could not be fit on page. It will not be plotted.case could not be fit on page. It will not be plotted.nothing could not be fit on page. It will not be plotted.shit could not be fit on page. It will not be plotted.econ could not be fit on page. It will not be plotted.fair could not be fit on page. It will not be plotted.school could not be fit on page. It will not be plotted.somewhere could not be fit on page. It will not be plotted.story could not be fit on page. It will not be plotted.times could not be fit on page. It will not be plotted.isabel could not be fit on page. It will not be plotted.movie could not be fit on page. It will not be plotted.needed could not be fit on page. It will not be plotted.sunday could not be fit on page. It will not be plotted.must could not be fit on page. It will not be plotted.different could not be fit on page. It will not be plotted.meant could not be fit on page. It will not be plotted.months could not be fit on page. It will not be plotted.mean could not be fit on page. It will not be plotted.play could not be fit on page. It will not be plotted.love could not be fit on page. It will not be plotted.may could not be fit on page. It will not be plotted.mom could not be fit on page. It will not be plotted.literally could not be fit on page. It will not be plotted.add could not be fit on page. It will not be plotted.nearly could not be fit on page. It will not be plotted.cycling could not be fit on page. It will not be plotted.enjoy could not be fit on page. It will not be plotted.involved could not be fit on page. It will not be plotted.october could not be fit on page. It will not be plotted.pain could not be fit on page. It will not be plotted.painful could not be fit on page. It will not be plotted.positive could not be fit on page. It will not be plotted.relationship could not be fit on page. It will not be plotted.risk could not be fit on page. It will not be plotted.staff could not be fit on page. It will not be plotted.unless could not be fit on page. It will not be plotted.use could not be fit on page. It will not be plotted.liam could not be fit on page. It will not be plotted.sorry could not be fit on page. It will not be plotted.guy could not be fit on page. It will not be plotted.guess could not be fit on page. It will not be plotted.book could not be fit on page. It will not be plotted.friends could not be fit on page. It will not be plotted.many could not be fit on page. It will not be plotted.address could not be fit on page. It will not be plotted.worst could not be fit on page. It will not be plotted.lol could not be fit on page. It will not be plotted.eating could not be fit on page. It will not be plotted.currently could not be fit on page. It will not be plotted.etc could not be fit on page. It will not be plotted.fire could not be fit on page. It will not be plotted.frisbee could not be fit on page. It will not be plotted.future could not be fit on page. It will not be plotted.offer could not be fit on page. It will not be plotted.sitting could not be fit on page. It will not be plotted.strange could not be fit on page. It will not be plotted.things could not be fit on page. It will not be plotted.person could not be fit on page. It will not be plotted.used could not be fit on page. It will not be plotted.actually could not be fit on page. It will not be plotted.class could not be fit on page. It will not be plotted.hopefully could not be fit on page. It will not be plotted.knew could not be fit on page. It will not be plotted.mei could not be fit on page. It will not be plotted.online could not be fit on page. It will not be plotted.tom could not be fit on page. It will not be plotted.video could not be fit on page. It will not be plotted.watching could not be fit on page. It will not be plotted.running could not be fit on page. It will not be plotted.set could not be fit on page. It will not be plotted.sort could not be fit on page. It will not be plotted.dating could not be fit on page. It will not be plotted.started could not be fit on page. It will not be plotted.together could not be fit on page. It will not be plotted.working could not be fit on page. It will not be plotted.goodi could not be fit on page. It will not be plotted.hey could not be fit on page. It will not be plotted.session could not be fit on page. It will not be plotted.shop could not be fit on page. It will not be plotted.afford could not be fit on page. It will not be plotted.ahead could not be fit on page. It will not be plotted.arrival could not be fit on page. It will not be plotted.border could not be fit on page. It will not be plotted.borough could not be fit on page. It will not be plotted.chatting could not be fit on page. It will not be plotted.confusing could not be fit on page. It will not be plotted.deals could not be fit on page. It will not be plotted.degrees could not be fit on page. It will not be plotted.depends could not be fit on page. It will not be plotted.dress could not be fit on page. It will not be plotted.edinburgh could not be fit on page. It will not be plotted.expecting could not be fit on page. It will not be plotted.gotta could not be fit on page. It will not be plotted.highly could not be fit on page. It will not be plotted.huge could not be fit on page. It will not be plotted.lateri could not be fit on page. It will not be plotted.law could not be fit on page. It will not be plotted.loved could not be fit on page. It will not be plotted.naked could not be fit on page. It will not be plotted.opened could not be fit on page. It will not be plotted.settle could not be fit on page. It will not be plotted.tidy could not be fit on page. It will not be plotted.tonighti could not be fit on page. It will not be plotted.even could not be fit on page. It will not be plotted.life could not be fit on page. It will not be plotted.pay could not be fit on page. It will not be plotted.name could not be fit on page. It will not be plotted.talked could not be fit on page. It will not be plotted.worth could not be fit on page. It will not be plotted.years could not be fit on page. It will not be plotted.comes could not be fit on page. It will not be plotted.obviously could not be fit on page. It will not be plotted.tea could not be fit on page. It will not be plotted.gave could not be fit on page. It will not be plotted.money could not be fit on page. It will not be plotted.also could not be fit on page. It will not be plotted.talk could not be fit on page. It will not be plotted.coffee could not be fit on page. It will not be plotted.makes could not be fit on page. It will not be plotted.extra could not be fit on page. It will not be plotted.question could not be fit on page. It will not be plotted.student could not be fit on page. It will not be plotted.appointment could not be fit on page. It will not be plotted.floors could not be fit on page. It will not be plotted.fly could not be fit on page. It will not be plotted.heat could not be fit on page. It will not be plotted.important could not be fit on page. It will not be plotted.matter could not be fit on page. It will not be plotted.seemed could not be fit on page. It will not be plotted.thesis could not be fit on page. It will not be plotted.wine could not be fit on page. It will not be plotted.read could not be fit on page. It will not be plotted.hate could not be fit on page. It will not be plotted.like could not be fit on page. It will not be plotted.close could not be fit on page. It will not be plotted.paper could not be fit on page. It will not be plotted.near could not be fit on page. It will not be plotted.american could not be fit on page. It will not be plotted.checked could not be fit on page. It will not be plotted.clearly could not be fit on page. It will not be plotted.asked could not be fit on page. It will not be plotted.mine could not be fit on page. It will not be plotted.walk could not be fit on page. It will not be plotted.allowed could not be fit on page. It will not be plotted.awful could not be fit on page. It will not be plotted.cold could not be fit on page. It will not be plotted.feels could not be fit on page. It will not be plotted.using could not be fit on page. It will not be plotted.definitely could not be fit on page. It will not be plotted.meet could not be fit on page. It will not be plotted.giving could not be fit on page. It will not be plotted.goes could not be fit on page. It will not be plotted.turn could not be fit on page. It will not be plotted.amazing could not be fit on page. It will not be plotted.living could not be fit on page. It will not be plotted.poor could not be fit on page. It will not be plotted.trying could not be fit on page. It will not be plotted.hope could not be fit on page. It will not be plotted.gone could not be fit on page. It will not be plotted.buy could not be fit on page. It will not be plotted.run could not be fit on page. It will not be plotted.alex could not be fit on page. It will not be plotted.saying could not be fit on page. It will not be plotted.hair could not be fit on page. It will not be plotted.friend could not be fit on page. It will not be plotted.just could not be fit on page. It will not be plotted.called could not be fit on page. It will not be plotted.real could not be fit on page. It will not be plotted.boys could not be fit on page. It will not be plotted.fun could not be fit on page. It will not be plotted.going could not be fit on page. It will not be plotted.hard could not be fit on page. It will not be plotted.idea could not be fit on page. It will not be plotted.year could not be fit on page. It will not be plotted.feel could not be fit on page. It will not be plotted.break could not be fit on page. It will not be plotted.interesting could not be fit on page. It will not be plotted.minute could not be fit on page. It will not be plotted.please could not be fit on page. It will not be plotted.london could not be fit on page. It will not be plotted.start could not be fit on page. It will not be plotted.ever could not be fit on page. It will not be plotted.needs could not be fit on page. It will not be plotted.chicago could not be fit on page. It will not be plotted.true could not be fit on page. It will not be plotted.christmas could not be fit on page. It will not be plotted.crazy could not be fit on page. It will not be plotted.care could not be fit on page. It will not be plotted.cheap could not be fit on page. It will not be plotted.exam could not be fit on page. It will not be plotted.sell could not be fit on page. It will not be plotted.sign could not be fit on page. It will not be plotted.tried could not be fit on page. It will not be plotted.website could not be fit on page. It will not be plotted.drama could not be fit on page. It will not be plotted.rent could not be fit on page. It will not be plotted.control could not be fit on page. It will not be plotted.convo could not be fit on page. It will not be plotted.dead could not be fit on page. It will not be plotted.face could not be fit on page. It will not be plotted.hand could not be fit on page. It will not be plotted.normally could not be fit on page. It will not be plotted.per could not be fit on page. It will not be plotted.places could not be fit on page. It will not be plotted.prefer could not be fit on page. It will not be plotted.rice could not be fit on page. It will not be plotted.surprised could not be fit on page. It will not be plotted.thoughts could not be fit on page. It will not be plotted.timei could not be fit on page. It will not be plotted.transfer could not be fit on page. It will not be plotted.visa could not be fit on page. It will not be plotted.anywhere could not be fit on page. It will not be plotted.bringing could not be fit on page. It will not be plotted.count could not be fit on page. It will not be plotted.cross could not be fit on page. It will not be plotted.deep could not be fit on page. It will not be plotted.massive could not be fit on page. It will not be plotted.middle could not be fit on page. It will not be plotted.pounds could not be fit on page. It will not be plotted.recent could not be fit on page. It will not be plotted.space could not be fit on page. It will not be plotted.stuck could not be fit on page. It will not be plotted.studying could not be fit on page. It will not be plotted.swimming could not be fit on page. It will not be plotted.town could not be fit on page. It will not be plotted.viking could not be fit on page. It will not be plotted.know could not be fit on page. It will not be plotted.can could not be fit on page. It will not be plotted.day could not be fit on page. It will not be plotted.free could not be fit on page. It will not be plotted.wanted could not be fit on page. It will not be plotted.better could not be fit on page. It will not be plotted.bring could not be fit on page. It will not be plotted.come could not be fit on page. It will not be plotted.sister could not be fit on page. It will not be plotted.stuff could not be fit on page. It will not be plotted.everything could not be fit on page. It will not be plotted.move could not be fit on page. It will not be plotted.long could not be fit on page. It will not be plotted.someone could not be fit on page. It will not be plotted.stop could not be fit on page. It will not be plotted.help could not be fit on page. It will not be plotted.hang could not be fit on page. It will not be plotted.write could not be fit on page. It will not be plotted.wrong could not be fit on page. It will not be plotted.look could not be fit on page. It will not be plotted.anyone could not be fit on page. It will not be plotted.wait could not be fit on page. It will not be plotted.climbing could not be fit on page. It will not be plotted.put could not be fit on page. It will not be plotted.apparently could not be fit on page. It will not be plotted.bag could not be fit on page. It will not be plotted.deal could not be fit on page. It will not be plotted.others could not be fit on page. It will not be plotted.ticket could not be fit on page. It will not be plotted.either could not be fit on page. It will not be plotted.making could not be fit on page. It will not be plotted.old could not be fit on page. It will not be plotted.asking could not be fit on page. It will not be plotted.lunch could not be fit on page. It will not be plotted.shall could not be fit on page. It will not be plotted.wow could not be fit on page. It will not be plotted.now could not be fit on page. It will not be plotted.week could not be fit on page. It will not be plotted.cool could not be fit on page. It will not be plotted.month could not be fit on page. It will not be plotted.thing could not be fit on page. It will not be plotted.ages could not be fit on page. It will not be plotted.non could not be fit on page. It will not be plotted.able could not be fit on page. It will not be plotted.time could not be fit on page. It will not be plotted.women could not be fit on page. It will not be plotted.yesterday could not be fit on page. It will not be plotted.weird could not be fit on page. It will not be plotted.appreciate could not be fit on page. It will not be plotted.bathroom could not be fit on page. It will not be plotted.longer could not be fit on page. It will not be plotted.normal could not be fit on page. It will not be plotted.parents could not be fit on page. It will not be plotted.pass could not be fit on page. It will not be plotted.putting could not be fit on page. It will not be plotted.questions could not be fit on page. It will not be plotted.rather could not be fit on page. It will not be plotted.sometimes could not be fit on page. It will not be plotted.works could not be fit on page. It will not be plotted.today could not be fit on page. It will not be plotted.believe could not be fit on page. It will not be plotted.chat could not be fit on page. It will not be plotted.sad could not be fit on page. It will not be plotted.wonder could not be fit on page. It will not be plotted.next could not be fit on page. It will not be plotted.got could not be fit on page. It will not be plotted.late could not be fit on page. It will not be plotted.said could not be fit on page. It will not be plotted.milk could not be fit on page. It will not be plotted.general could not be fit on page. It will not be plotted.join could not be fit on page. It will not be plotted.board could not be fit on page. It will not be plotted.contact could not be fit on page. It will not be plotted.fact could not be fit on page. It will not be plotted.none could not be fit on page. It will not be plotted.test could not be fit on page. It will not be plotted.tough could not be fit on page. It will not be plotted.welcome could not be fit on page. It will not be plotted.window could not be fit on page. It will not be plotted.ask could not be fit on page. It will not be plotted.reading could not be fit on page. It will not be plotted.bad could not be fit on page. It will not be plotted.weeks could not be fit on page. It will not be plotted.earlier could not be fit on page. It will not be plotted.kitchen could not be fit on page. It will not be plotted.party could not be fit on page. It will not be plotted.woman could not be fit on page. It will not be plotted.worked could not be fit on page. It will not be plotted.aim could not be fit on page. It will not be plotted.amount could not be fit on page. It will not be plotted.attention could not be fit on page. It will not be plotted.choice could not be fit on page. It will not be plotted.clothes could not be fit on page. It will not be plotted.code could not be fit on page. It will not be plotted.cost could not be fit on page. It will not be plotted.moth could not be fit on page. It will not be plotted.ordered could not be fit on page. It will not be plotted.photos could not be fit on page. It will not be plotted.therei could not be fit on page. It will not be plotted.remember could not be fit on page. It will not be plotted.bed could not be fit on page. It will not be plotted.want could not be fit on page. It will not be plotted.getting could not be fit on page. It will not be plotted.told could not be fit on page. It will not be plotted.right could not be fit on page. It will not be plotted.another could not be fit on page. It will not be plotted.bank could not be fit on page. It will not be plotted.talking could not be fit on page. It will not be plotted.early could not be fit on page. It will not be plotted.hours could not be fit on page. It will not be plotted.baby could not be fit on page. It will not be plotted.current could not be fit on page. It will not be plotted.final could not be fit on page. It will not be plotted.friday could not be fit on page. It will not be plotted.mess could not be fit on page. It will not be plotted.check could not be fit on page. It will not be plotted.end could not be fit on page. It will not be plotted.keep could not be fit on page. It will not be plotted.watch could not be fit on page. It will not be plotted.felt could not be fit on page. It will not be plotted.seem could not be fit on page. It will not be plotted.team could not be fit on page. It will not be plotted.understand could not be fit on page. It will not be plotted.tomorrow could not be fit on page. It will not be plotted.much could not be fit on page. It will not be plotted.tonight could not be fit on page. It will not be plotted.came could not be fit on page. It will not be plotted.stay could not be fit on page. It will not be plotted.always could not be fit on page. It will not be plotted.don could not be fit on page. It will not be plotted.people could not be fit on page. It will not be plotted.feeling could not be fit on page. It will not be plotted.number could not be fit on page. It will not be plotted.thank could not be fit on page. It will not be plotted.cleaning could not be fit on page. It will not be plotted.likely could not be fit on page. It will not be plotted.short could not be fit on page. It will not be plotted.staying could not be fit on page. It will not be plotted.throw could not be fit on page. It will not be plotted.thurs could not be fit on page. It will not be plotted.find could not be fit on page. It will not be plotted.david could not be fit on page. It will not be plotted.august could not be fit on page. It will not be plotted.world could not be fit on page. It will not be plotted.see could not be fit on page. It will not be plotted.waiting could not be fit on page. It will not be plotted.done could not be fit on page. It will not be plotted.ish could not be fit on page. It will not be plotted.open could not be fit on page. It will not be plotted.looking could not be fit on page. It will not be plotted.gets could not be fit on page. It will not be plotted.miss could not be fit on page. It will not be plotted.one could not be fit on page. It will not be plotted.make could not be fit on page. It will not be plotted.quite could not be fit on page. It will not be plotted.head could not be fit on page. It will not be plotted.need could not be fit on page. It will not be plotted.since could not be fit on page. It will not be plotted.btw could not be fit on page. It will not be plotted.decide could not be fit on page. It will not be plotted.event could not be fit on page. It will not be plotted.experience could not be fit on page. It will not be plotted.happens could not be fit on page. It will not be plotted.lost could not be fit on page. It will not be plotted.moved could not be fit on page. It will not be plotted.sick could not be fit on page. It will not be plotted.study could not be fit on page. It will not be plotted.thinks could not be fit on page. It will not be plotted.call could not be fit on page. It will not be plotted.get could not be fit on page. It will not be plotted.still could not be fit on page. It will not be plotted.think could not be fit on page. It will not be plotted.hour could not be fit on page. It will not be plotted.couldn could not be fit on page. It will not be plotted.data could not be fit on page. It will not be plotted.omitted could not be fit on page. It will not be plotted.two could not be fit on page. It will not be plotted.sleep could not be fit on page. It will not be plotted.train could not be fit on page. It will not be plotted.way could not be fit on page. It will not be plotted.best could not be fit on page. It will not be plotted.happened could not be fit on page. It will not be plotted.tell could not be fit on page. It will not be plotted.say could not be fit on page. It will not be plotted.leaving could not be fit on page. It will not be plotted.happy could not be fit on page. It will not be plotted.top could not be fit on page. It will not be plotted.saw could not be fit on page. It will not be plotted.problem could not be fit on page. It will not be plotted.second could not be fit on page. It will not be plotted.card could not be fit on page. It will not be plotted.decided could not be fit on page. It will not be plotted.drink could not be fit on page. It will not be plotted.street could not be fit on page. It will not be plotted.flights could not be fit on page. It will not be plotted.notice could not be fit on page. It will not be plotted.warm could not be fit on page. It will not be plotted.answer could not be fit on page. It will not be plotted.financial could not be fit on page. It will not be plotted.hanging could not be fit on page. It will not be plotted.invited could not be fit on page. It will not be plotted.itwe could not be fit on page. It will not be plotted.jobs could not be fit on page. It will not be plotted.leaves could not be fit on page. It will not be plotted.related could not be fit on page. It will not be plotted.slow could not be fit on page. It will not be plotted.sound could not be fit on page. It will not be plotted.table could not be fit on page. It will not be plotted.taken could not be fit on page. It will not be plotted.wake could not be fit on page. It will not be plotted.maybe could not be fit on page. It will not be plotted.thought could not be fit on page. It will not be plotted.last could not be fit on page. It will not be plotted.days could not be fit on page. It will not be plotted.mind could not be fit on page. It will not be plotted.will could not be fit on page. It will not be plotted.everyone could not be fit on page. It will not be plotted.aren could not be fit on page. It will not be plotted.booked could not be fit on page. It will not be plotted.funny could not be fit on page. It will not be plotted.looked could not be fit on page. It will not be plotted.ones could not be fit on page. It will not be plotted.seen could not be fit on page. It will not be plotted.busy could not be fit on page. It will not be plotted.half could not be fit on page. It will not be plotted.wear could not be fit on page. It will not be plotted.well could not be fit on page. It will not be plotted.give could not be fit on page. It will not be plotted.easyjet could not be fit on page. It will not be plotted.floor could not be fit on page. It will not be plotted.june could not be fit on page. It will not be plotted.totally could not be fit on page. It will not be plotted.new could not be fit on page. It will not be plotted.thinking could not be fit on page. It will not be plotted.later could not be fit on page. It will not be plotted.might could not be fit on page. It will not be plotted.credit could not be fit on page. It will not be plotted.invite could not be fit on page. It will not be plotted.market could not be fit on page. It will not be plotted.paid could not be fit on page. It will not be plotted.plane could not be fit on page. It will not be plotted.side could not be fit on page. It will not be plotted.soooo could not be fit on page. It will not be plotted.spend could not be fit on page. It will not be plotted.weekend could not be fit on page. It will not be plotted.anything could not be fit on page. It will not be plotted.flat could not be fit on page. It will not be plotted.mins could not be fit on page. It will not be plotted.flight could not be fit on page. It will not be plotted.interview could not be fit on page. It will not be plotted.outside could not be fit on page. It will not be plotted.wish could not be fit on page. It will not be plotted.without could not be fit on page. It will not be plotted.glad could not be fit on page. It will not be plotted.arrive could not be fit on page. It will not be plotted.arrived could not be fit on page. It will not be plotted.city could not be fit on page. It will not be plotted.closer could not be fit on page. It will not be plotted.given could not be fit on page. It will not be plotted.police could not be fit on page. It will not be plotted.pop could not be fit on page. It will not be plotted.single could not be fit on page. It will not be plotted.standing could not be fit on page. It will not be plotted.steps could not be fit on page. It will not be plotted.thanks could not be fit on page. It will not be plotted.take could not be fit on page. It will not be plotted.part could not be fit on page. It will not be plotted.super could not be fit on page. It will not be plotted.blue could not be fit on page. It will not be plotted.bread could not be fit on page. It will not be plotted.brunch could not be fit on page. It will not be plotted.worried could not be fit on page. It will not be plotted.nice could not be fit on page. It will not be plotted.date could not be fit on page. It will not be plotted.job could not be fit on page. It will not be plotted.wants could not be fit on page. It will not be plotted.home could not be fit on page. It will not be plotted.match could not be fit on page. It will not be plotted.exactly could not be fit on page. It will not be plotted.night could not be fit on page. It will not be plotted.sure could not be fit on page. It will not be plotted.nope could not be fit on page. It will not be plotted.first could not be fit on page. It will not be plotted.leave could not be fit on page. It will not be plotted.coming could not be fit on page. It will not be plotted.great could not be fit on page. It will not be plotted.house could not be fit on page. It will not be plotted.office could not be fit on page. It will not be plotted.less could not be fit on page. It will not be plotted.past could not be fit on page. It will not be plotted.three could not be fit on page. It will not be plotted.lucky could not be fit on page. It will not be plotted.mad could not be fit on page. It will not be plotted.photo could not be fit on page. It will not be plotted.back could not be fit on page. It will not be plotted.annoying could not be fit on page. It will not be plotted.forgot could not be fit on page. It will not be plotted.high could not be fit on page. It will not be plotted.yay could not be fit on page. It will not be plotted.yet could not be fit on page. It will not be plotted.happen could not be fit on page. It will not be plotted.room could not be fit on page. It will not be plotted.though could not be fit on page. It will not be plotted.enough could not be fit on page. It will not be plotted.summer could not be fit on page. It will not be plotted.made could not be fit on page. It will not be plotted.phone could not be fit on page. It will not be plotted.worry could not be fit on page. It will not be plotted.german could not be fit on page. It will not be plotted.imagine could not be fit on page. It will not be plotted.clean could not be fit on page. It will not be plotted.small could not be fit on page. It will not be plotted.whole could not be fit on page. It will not be plotted.gym could not be fit on page. It will not be plotted.plan could not be fit on page. It will not be plotted.taking could not be fit on page. It will not be plotted.yeah could not be fit on page. It will not be plotted.message could not be fit on page. It will not be plotted.eggs could not be fit on page. It will not be plotted.family could not be fit on page. It will not be plotted.finish could not be fit on page. It will not be plotted.loves could not be fit on page. It will not be plotted.wrote could not be fit on page. It will not be plotted.morning could not be fit on page. It will not be plotted.business could not be fit on page. It will not be plotted.planning could not be fit on page. It will not be plotted.email could not be fit on page. It will not be plotted.fridge could not be fit on page. It will not be plotted.heard could not be fit on page. It will not be plotted.says could not be fit on page. It will not be plotted.away could not be fit on page. It will not be plotted.airport could not be fit on page. It will not be plotted.cheese could not be fit on page. It will not be plotted.google could not be fit on page. It will not be plotted.Column `word` joining factors with different levels, coercing to character vector

trains could not be fit on page. It will not be plotted.holiday could not be fit on page. It will not be plotted.evening could not be fit on page. It will not be plotted.surprises could not be fit on page. It will not be plotted.hahai could not be fit on page. It will not be plotted.enjoyed could not be fit on page. It will not be plotted.restaurant could not be fit on page. It will not be plotted.weren could not be fit on page. It will not be plotted.breakfast could not be fit on page. It will not be plotted.daily could not be fit on page. It will not be plotted.expert could not be fit on page. It will not be plotted.salary could not be fit on page. It will not be plotted.tree could not be fit on page. It will not be plotted.easyjet could not be fit on page. It will not be plotted.ready could not be fit on page. It will not be plotted.article could not be fit on page. It will not be plotted.borough could not be fit on page. It will not be plotted.boy could not be fit on page. It will not be plotted.checking could not be fit on page. It will not be plotted.marketing could not be fit on page. It will not be plotted.period could not be fit on page. It will not be plotted.sheets could not be fit on page. It will not be plotted.wondering could not be fit on page. It will not be plotted.manager could not be fit on page. It will not be plotted.round could not be fit on page. It will not be plotted.english could not be fit on page. It will not be plotted.moth could not be fit on page. It will not be plotted.loads could not be fit on page. It will not be plotted.dumb could not be fit on page. It will not be plotted.quick could not be fit on page. It will not be plotted.soooo could not be fit on page. It will not be plotted.family could not be fit on page. It will not be plotted.expect could not be fit on page. It will not be plotted.leaves could not be fit on page. It will not be plotted.cheapest could not be fit on page. It will not be plotted.scared could not be fit on page. It will not be plotted.september could not be fit on page. It will not be plotted.step could not be fit on page. It will not be plotted.quite could not be fit on page. It will not be plotted.funny could not be fit on page. It will not be plotted.small could not be fit on page. It will not be plotted.couple could not be fit on page. It will not be plotted.message could not be fit on page. It will not be plotted.worked could not be fit on page. It will not be plotted.hadn could not be fit on page. It will not be plotted.therei could not be fit on page. It will not be plotted.took could not be fit on page. It will not be plotted.great could not be fit on page. It will not be plotted.market could not be fit on page. It will not be plotted.lots could not be fit on page. It will not be plotted.thanks could not be fit on page. It will not be plotted.wouldn could not be fit on page. It will not be plotted.door could not be fit on page. It will not be plotted.plans could not be fit on page. It will not be plotted.change could not be fit on page. It will not be plotted.event could not be fit on page. It will not be plotted.happens could not be fit on page. It will not be plotted.train could not be fit on page. It will not be plotted.pick could not be fit on page. It will not be plotted.away could not be fit on page. It will not be plotted.came could not be fit on page. It will not be plotted.morning could not be fit on page. It will not be plotted.card could not be fit on page. It will not be plotted.street could not be fit on page. It will not be plotted.secret could not be fit on page. It will not be plotted.weather could not be fit on page. It will not be plotted.answer could not be fit on page. It will not be plotted.giant could not be fit on page. It will not be plotted.internet could not be fit on page. It will not be plotted.invited could not be fit on page. It will not be plotted.normally could not be fit on page. It will not be plotted.weekend could not be fit on page. It will not be plotted.boys could not be fit on page. It will not be plotted.looked could not be fit on page. It will not be plotted.agree could not be fit on page. It will not be plotted.half could not be fit on page. It will not be plotted.landlord could not be fit on page. It will not be plotted.longer could not be fit on page. It will not be plotted.happen could not be fit on page. It will not be plotted.others could not be fit on page. It will not be plotted.water could not be fit on page. It will not be plotted.board could not be fit on page. It will not be plotted.cafe could not be fit on page. It will not be plotted.canada could not be fit on page. It will not be plotted.single could not be fit on page. It will not be plotted.welcome could not be fit on page. It will not be plotted.whether could not be fit on page. It will not be plotted.everyone could not be fit on page. It will not be plotted.eggs could not be fit on page. It will not be plotted.likely could not be fit on page. It will not be plotted.messages could not be fit on page. It will not be plotted.sign could not be fit on page. It will not be plotted.thurs could not be fit on page. It will not be plotted.hasn could not be fit on page. It will not be plotted.night could not be fit on page. It will not be plotted.christmas could not be fit on page. It will not be plotted.decided could not be fit on page. It will not be plotted.find could not be fit on page. It will not be plotted.booked could not be fit on page. It will not be plotted.ever could not be fit on page. It will not be plotted.kind could not be fit on page. It will not be plotted.went could not be fit on page. It will not be plotted.though could not be fit on page. It will not be plotted.freezer could not be fit on page. It will not be plotted.less could not be fit on page. It will not be plotted.dating could not be fit on page. It will not be plotted.flights could not be fit on page. It will not be plotted.goes could not be fit on page. It will not be plotted.turn could not be fit on page. It will not be plotted.closed could not be fit on page. It will not be plotted.cooking could not be fit on page. It will not be plotted.course could not be fit on page. It will not be plotted.finished could not be fit on page. It will not be plotted.study could not be fit on page. It will not be plotted.thinks could not be fit on page. It will not be plotted.back could not be fit on page. It will not be plotted.good could not be fit on page. It will not be plotted.match could not be fit on page. It will not be plotted.annoying could not be fit on page. It will not be plotted.talking could not be fit on page. It will not be plotted.yay could not be fit on page. It will not be plotted.always could not be fit on page. It will not be plotted.play could not be fit on page. It will not be plotted.paid could not be fit on page. It will not be plotted.made could not be fit on page. It will not be plotted.think could not be fit on page. It will not be plotted.awful could not be fit on page. It will not be plotted.floor could not be fit on page. It will not be plotted.june could not be fit on page. It will not be plotted.works could not be fit on page. It will not be plotted.super could not be fit on page. It will not be plotted.something could not be fit on page. It will not be plotted.airport could not be fit on page. It will not be plotted.happened could not be fit on page. It will not be plotted.amazing could not be fit on page. It will not be plotted.exactly could not be fit on page. It will not be plotted.luck could not be fit on page. It will not be plotted.really could not be fit on page. It will not be plotted.definitely could not be fit on page. It will not be plotted.flight could not be fit on page. It will not be plotted.phone could not be fit on page. It will not be plotted.number could not be fit on page. It will not be plotted.women could not be fit on page. It will not be plotted.cheap could not be fit on page. It will not be plotted.loves could not be fit on page. It will not be plotted.short could not be fit on page. It will not be plotted.staying could not be fit on page. It will not be plotted.worried could not be fit on page. It will not be plotted.help could not be fit on page. It will not be plotted.case could not be fit on page. It will not be plotted.world could not be fit on page. It will not be plotted.interesting could not be fit on page. It will not be plotted.planning could not be fit on page. It will not be plotted.maybe could not be fit on page. It will not be plotted.close could not be fit on page. It will not be plotted.pretty could not be fit on page. It will not be plotted.waiting could not be fit on page. It will not be plotted.dinner could not be fit on page. It will not be plotted.yeah could not be fit on page. It will not be plotted.people could not be fit on page. It will not be plotted.ages could not be fit on page. It will not be plotted.hour could not be fit on page. It will not be plotted.apparently could not be fit on page. It will not be plotted.gets could not be fit on page. It will not be plotted.hopefully could not be fit on page. It will not be plotted.whole could not be fit on page. It will not be plotted.around could not be fit on page. It will not be plotted.coming could not be fit on page. It will not be plotted.called could not be fit on page. It will not be plotted.date could not be fit on page. It will not be plotted.check could not be fit on page. It will not be plotted.end could not be fit on page. It will not be plotted.wants could not be fit on page. It will not be plotted.yesterday could not be fit on page. It will not be plotted.means could not be fit on page. It will not be plotted.weeks could not be fit on page. It will not be plotted.cheese could not be fit on page. It will not be plotted.hope could not be fit on page. It will not be plotted.anything could not be fit on page. It will not be plotted.london could not be fit on page. It will not be plotted.days could not be fit on page. It will not be plotted.summer could not be fit on page. It will not be plotted.asked could not be fit on page. It will not be plotted.thinking could not be fit on page. It will not be plotted.bring could not be fit on page. It will not be plotted.question could not be fit on page. It will not be plotted.understand could not be fit on page. It will not be plotted.
[[1]]
NULL

[[2]]
NULL

[[3]]
NULL

[[4]]
NULL

[[5]]
NULL

Words said over time

So now I need to replicate some of the work I did earlier, namely plotting the frequency of words over time

#step 1:
#count the number of times a word appears by date
tmp %>% group_by(date) %>% summarise(number = n())

who talks to who the most

Duplicate the functions above, but apply it to individual words

#write a function that looks at most frequent reponders
response_summary_word <- function(df, person, type, word){
library(scales)
library(magrittr)
#select sender 
  tmp <- df 
  tmp$indicator <- 0 
  if (length(tmp[tmp$sender == person & grepl(word, tmp$message),]$indicator) > 0){
    tmp[tmp$sender == person & grepl(word, tmp$message),]$indicator <- 1 
  } else { 
    tmp$indicator <- 0
  }
  tmp$indicator <- lag(tmp$indicator)
  tmp %<>% mutate(indicator = ifelse(is.na(indicator), 0, indicator))
#calculate total messages by sender 
  tmp <- tmp %>% group_by(sender) %>%
    mutate(total_messages = n()) 
  
if (type == 1){ tmp %>% group_by(sender) %>% summarise(total_responses = sum(na.omit(indicator)))
} else if (type == 2){tmp %>% group_by(sender) %>%
    mutate(total_responses_to_sender = sum(na.omit(indicator))) %>%
    mutate(done = total_responses_to_sender/total_messages) %>% 
    summarise("% of all messages made in response to sender" = percent(mean(done)))} }
response_summary_word(tmp, "Robert", type = 1, word="sex")
# Create a response matrix
response_matrix_word <- function(df, type, word){
senders <- response_summary(df, df$sender[[1]], type = 1)$sender
responses_total <- cbind(as.data.frame(lapply(senders, function(x)
response_summary_word(df, x, type = type, word = word)[,2]))) 
names(responses_total) <- senders 
row.names(responses_total) <- senders 
responses_total
}
response_matrix_word(tmp, 1, word = "lol")
Error in `[<-.data.frame`(`*tmp*`, tmp$sender == person, , value = list( : 
  missing values are not allowed in subscripted assignments of data frames

Next: write some of the functions using SE

library(lubridate)
#select groups usinge SE
freq_plot <- function(df, word, v1, v2){
 df %>% mutate(date = mdy(date)) %>%
  group_by_(v1, v2) %>%
  filter(grepl(word, message)) %>%  
  summarise(count = n()) %>%
  ggplot(aes(x = date, y = count, color = sender)) + geom_point() + ylim(0,NA) + theme_bw() }
freq_plot(tmp, ".", v1 = "sender", v2 = "date")

#summary table of two variable
tw_tab <- function(df, v1, v2){
tmp <- df
tmp %>% group_by_(v1, v2) %>% 
  mutate(tot=n()) %>% 
  ungroup() %>% 
  group_by_(v1) %>% 
  mutate(perc = tot/n()) %>% 
  ungroup() %>% group_by_(v1, v2) %>% 
  summarise(end = mean(perc)) %>% dcast(paste(v1, '~', v2), value.var = "end")
}
# plot share of conversation over time 
tw_tab(tmp, "date", "sender") %>%
  mutate(date = mdy(date)) %>% 
  melt(id.vars="date") %>% 
  ggplot(aes(x = date, y = value, color = variable, fill = variable)) + geom_col()

Next: turn the response matrix into a network diagram

In order to do this I basically want to depict the relationships between people and how important people are to the conversation.

Features include:

library(visNetwork) 
library(igraph)
# Create nodes data.frame
library(dplyr) 
library(magrittr)
# create names
nodes <- data.frame(select(tmp, sender) %>% distinct()) 
names(nodes) <- "id"
# create number of messages sent 
totals <- select(tmp, sender) %>%
  group_by(sender) %>% 
  summarise(sum = n()) 
nodes$size <- (totals$sum *100)/sum(totals$sum)
# Create edges of data.frame 
responses <- response_matrix(tmp, 1) 
responses <-as.data.frame(responses)
responses$name <- row.names(responses) 
responses_m <- melt(responses) 
Using name as id variables
names(responses_m) <- c("from","to", "number")
# format as network
edges <- responses_m 
edges$to <- as.character(edges$to) 
edges$width <- (edges$number * 100)/sum(totals$sum)
edges$title <- paste("<p style=\"color:black\">",edges$number,"</p>")
# add in node colors, names 
nodes$group <- nodes$id 
nodes$label <- nodes$id 
nodes$title <- paste("<p style=\"color: black\">",totals$sum,"</p>")
# plot library(visNetwork) 
visNetwork(nodes, edges, width = "100%") %>%
visPhysics( solver ='forceAtlas2Based')

New additions:

Count number of words


# Create variable that is number of words per message

test <- "this message has many words in it"
length(unlist(strsplit(test, split = " ")))

test2 <- data.frame(c = c("message with three", "message with two"), stringsAsFactors = FALSE)
str(test2)
length(unlist(strsplit(test2$c, split = " ")))


library(stringr)

# create variable with number of words in each line

tmp %<>% ungroup
tmp %>% mutate(number_words = str_count(message, " ")) %>% group_by(sender) %>% summarise(total_words = sum(number_words), avg_message_length = total_words/mean(total_messages))

Word sepecific matrix

responses <- response_matrix_word(tmp, 1, word = "sex") 
Called from: response_summary_word(df, x, type = type, word = word)
function(df, person, type, word){
browser()
library(scales)
library(magrittr)
#select sender 
  tmp <- df 
  tmp$indicator <- 0 
  if (length(tmp[tmp$sender == person & grepl(word, tmp$message),]$indicator) > 0){
    tmp[tmp$sender == person & grepl(word, tmp$message),]$indicator <- 1 
  } else { 
    tmp$indicator <- 0
  }
  tmp$indicator <- lag(tmp$indicator)
  tmp %<>% mutate(indicator = ifelse(is.na(indicator), 0, indicator))
#calculate total messages by sender 
  tmp <- tmp %>% group_by(sender) %>%
    mutate(total_messages = n()) 
  
if (type == 1){ tmp %>% group_by(sender) %>% summarise(total_responses = sum(na.omit(indicator)))
} else if (type == 2){tmp %>% group_by(sender) %>%
    mutate(total_responses_to_sender = sum(na.omit(indicator))) %>%
    mutate(done = total_responses_to_sender/total_messages) %>% 
    summarise("% of all messages made in response to sender" = percent(mean(done)))} }
function(df, person, type, word){
browser()
library(scales)
library(magrittr)
#select sender 
  tmp <- df 
  tmp$indicator <- 0 
  if (length(tmp[tmp$sender == person & grepl(word, tmp$message),]$indicator) > 0){
    tmp[tmp$sender == person & grepl(word, tmp$message),]$indicator <- 1 
  } else { 
    tmp$indicator <- 0
  }
  tmp$indicator <- lag(tmp$indicator)
  tmp %<>% mutate(indicator = ifelse(is.na(indicator), 0, indicator))

#calculate total messages by sender 
  tmp <- tmp %>% group_by(sender) %>%
    mutate(total_messages = n()) 
  

if (type == 1){ tmp %>% group_by(sender) %>% summarise(total_responses = sum(na.omit(indicator)))

} else if (type == 2){tmp %>% group_by(sender) %>%
    mutate(total_responses_to_sender = sum(na.omit(indicator))) %>%
    mutate(done = total_responses_to_sender/total_messages) %>% 
    summarise("% of all messages made in response to sender" = percent(mean(done)))} }
<environment: 0x000000001b66df18>
Q

Create shiny app

The first stage of creating this shiny app is just making it so that the user can select (via an input box) what word the would like to look at the network of.

Ideally I would then also make it so the can just look at the matrix of all messages sent (or perhaps have this as a seperate part of the app for comparison purposes).

Later stages of the app should then add some additional summary measures (person specific word cloud, messages sent over time, messages sent over time containing a particular word, etc).

## Setup
# create names
nodes <- data.frame(select(tmp, sender) %>% distinct()) 
names(nodes) <- "id"
# add in node colors, names 
nodes$group <- nodes$id 
nodes$label <- nodes$id 
nodes$title <- paste("<p style=\"color: black\">",totals$sum,"</p>")
require(shiny)
require(visNetwork)
server <- function(input, output) {
  output$network <- renderVisNetwork({
 
    # create number of messages sent for node size
    word <- "sex"
    
    totals <- select(tmp, sender, message) %>%
      mutate(ind = ifelse(grepl(word, tmp$message), 1, 0)) %>% 
      group_by(sender) %>% 
      summarise(sum = sum(ind)) 
    
    nodes$size <- pmax((totals$sum *100)/sum(totals$sum), 0.75)
    
    # create response matrix
    
    # Create edges of data.frame 
    responses <- response_matrix_word(tmp, 1, word = input$word) 
    
    responses <-as.data.frame(responses)
    responses_t <- t(responses) #so that melt correctly picks up to and from
    responses_m <- melt(responses_t) 
    names(responses_m) <- c("from","to", "number")
    
    # format as network
    
    edges <- responses_m 
    edges$to <- as.character(edges$to) 
    edges$width <- (edges$number * 50)/sum(edges$number)
    edges$title <- paste("<p style=\"color:black\">",edges$number,"</p>")
    edges <- edges[edges$number > 0,]
    
    # render network 
    visNetwork(nodes, edges) %>%
      visPhysics( solver ='forceAtlas2Based')
  })
}
ui <- fluidPage(
  
    # create user input word box 
    textInput("word", "Word", value = "hi"),
    # render output
    visNetworkOutput("network")
)
shinyApp(ui = ui, server = server)

Listening on http://127.0.0.1:4576

Create an app that takes a whatsapp file as input

This is the first stage of creating the end user shiny application. It needs to be able to load any whatsapp file and produce basic analysis like the network above.

In the first instance I’m just going to get it to load a file, format as a data.frame, and then print the first 10 rows of that data.frame.

currently built shiny app

Notes: I am concerned that this actually depends on the value of tmp in the other data (rather than what is loaded).

Going to test this by changing to tmp1. All still seems to work

library(tidyverse)
library(shiny)
library(visNetwork)
ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      fileInput("file1", "Choose CSV File",
        accept = c(
          "text/csv",
          "text/comma-separated-values,text/plain",
          ".csv")
        ),
      tags$hr(),
      checkboxInput("header", "Header", TRUE),    
      
      # create user input word box 
      textInput("word", "Word", value = "hi")
   
    ),
    mainPanel(
       
      # render output
      visNetworkOutput("network")
      
      
    )
  )
)
server <- function(input, output) {
    # Create Network  
    output$network <- renderVisNetwork({
    
    
    # input$file1 will be NULL initially. After the user selects
    # and uploads a file, it will be a data frame
    inFile <- input$file1
    if (is.null(inFile))
      return(NULL)
    loaded_chat <- read.table(inFile$datapath,  
                                fill=TRUE, header=input$header, quote="", sep="\n", encoding="UTF-8")
    names(loaded_chat) <- "string"
     
    # format the data and split into different columns
    regx <- "(\\d+/\\d+/\\d+),\\s+(\\d+:\\d+:\\d+ [A|P]M):\\s+(\\w+\\s*\\w+):\\s+(.*)"
    tmp <- loaded_chat %>%
         tidyr::extract(string, c("date", "time", "sender", "message"), regx, remove=FALSE)
     
     tmp <- filter(tmp, !is.na(sender))
     
    # create nodes list
    nodes <- data.frame(select(tmp, sender) %>% distinct()) 
    names(nodes) <- "id"
    # add in node colors, names 
    nodes$group <- nodes$id 
    nodes$label <- nodes$id
    #create number of messages sent for node size
    totals <- select(tmp, sender, message) %>%
      mutate(ind = ifelse(grepl(input$word, message), 1, 0)) %>%
      group_by(sender) %>%
      summarise(total_messages = sum(ind))
  
    nodes <- left_join(nodes, totals, by=c("id"="sender"))
    nodes$size <- pmax((nodes$total_messages *100)/sum(nodes$total_messages), 75/sum(nodes$total_messages))
    nodes$title <- paste("<p style=\"color: black\">",nodes$total_messages,"</p>")
    
    # create response matrix
    responses <- response_matrix_word(tmp, 1, word = input$word)
    responses <-as.data.frame(responses)
    responses_t <- t(responses) #so that melt correctly picks up to and from
    responses_m <- melt(responses_t)
    names(responses_m) <- c("from","to", "number")
    
    
    # format as network edges
    edges <- responses_m 
    edges$to <- as.character(edges$to) 
    edges$width <- (edges$number * 50)/sum(edges$number)
    edges$title <- paste("<p style=\"color:black\">",edges$number,"</p>")
    edges <- edges[edges$number > 0,]
    # render network 
    visNetwork(nodes, edges) %>%
      visPhysics( solver ='forceAtlas2Based')
  })
  
  
}
shinyApp(ui, server)

Listening on http://127.0.0.1:6243
Error in $<-.data.frame: replacement has 1 row, data has 0Stack trace (innermost first):
    89: $<-.data.frame
    88: $<- [#8]
    87: response_summary_word [#8]
    86: FUN [#5]
    85: lapply
    84: as.data.frame [#5]
    83: cbind [#5]
    82: response_matrix_word [#5]
    81: func [#46]
    80: origRenderFunc
    79: output$network
     4: <Anonymous>
     3: do.call
     2: print.shiny.appobj
     1: <Promise>

get it working pre shiny app

library(data.table)
library(tidyr)
    
    #chat <- fread("C:/Users/rober/Desktop/text.csv", blank.lines.skip = TRUE)
    tmp1 <- read.table("C:/Users/rober/Desktop/chat2.txt",  fill=TRUE, header=TRUE, quote="", sep="\n", encoding="UTF-8")
    names(tmp1) <- "string"

    # format the data and split into different columns
    regx <- "(\\d+/\\d+/\\d+),\\s+(\\d+:\\d+:\\d+ [A|P]M):\\s+(\\w+\\s*\\w+):\\s+(.*)"
    tmp1 <- tmp1 %>%
        tidyr::extract(string, c("date", "time", "sender", "message"), regx, remove=FALSE)

    
    tmp1 <- filter(tmp1, !is.na(sender))
    
    # create nodes list
    nodes <- data.frame(select(tmp1, sender) %>% distinct()) 
    names(nodes) <- "id"

    # add in node colors, names 
    nodes$group <- nodes$id 
    nodes$label <- nodes$id
    
    # create number of messages sent for node size
    word = "hi"
    
    totals <- select(tmp1, sender, message) %>%
      mutate(ind = ifelse(grepl(word, tmp1$message), 1, 0)) %>% 
      group_by(sender) %>% 
      summarise(sum = sum(ind)) 
    
    nodes <- left_join(nodes, totals, by=c("id"="sender"))
    nodes$size <- pmax((nodes$sum *100)/sum(nodes$sum), 75/sum(nodes$sum))
    nodes$title <- paste("<p style=\"color: black\">",nodes$sum,"</p>")
    
    # create response matrix
    responses <- response_matrix_word(tmp1, 1, word = word) 
    responses <-as.data.frame(responses)
    responses_t <- t(responses) #so that melt correctly picks up to and from
    responses_m <- melt(responses_t) 
    names(responses_m) <- c("from","to", "number")
    
    # format as network edges
    edges <- responses_m 
    edges$to <- as.character(edges$to) 
    edges$width <- (edges$number * 50)/sum(edges$number)
    edges$title <- paste("<p style=\"color:black\">",edges$number,"</p>")
    edges <- edges[edges$number > 0,]

    # render network 
    visNetwork(nodes, edges) %>%
    visPhysics( solver ='forceAtlas2Based')
    
totals
edges %>% group_by(from) %>% summarise(n=sum(number))
responses_m   

Table version (rather than network)

Useful for testing out code

## Only run examples in interactive R sessions
if (interactive()) {

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      fileInput("file1", "Choose CSV File",
        accept = c(
          "text/csv",
          "text/comma-separated-values,text/plain",
          ".csv",
          ".txt")
        ),
      tags$hr(),
      checkboxInput("header", "Header", TRUE),
      
      # create user input word box 
      textInput("word", "Word", value = "hi")
      
    ),
    mainPanel(
      tableOutput("contents")
    )
  )
)

server <- function(input, output) {
  output$contents <- renderTable({
    # input$file1 will be NULL initially. After the user selects
    # and uploads a file, it will be a data frame with 'name',
    # 'size', 'type', and 'datapath' columns. The 'datapath'
    # column will contain the local filenames where the data can
    # be found.
    inFile <- input$file1

    if (is.null(inFile))
      return(NULL)

      loaded_chat <- read.table(inFile$datapath,  fill=TRUE, header=input$header, quote="", sep="\n", encoding="UTF-8")
      names(loaded_chat) <- "string"
      loaded_chat
     
    # format the data and split into different columns
     regx <- "(\\d+/\\d+/\\d+),\\s+(\\d+:\\d+:\\d+ [A|P]M):\\s+(\\w+\\s*\\w+):\\s+(.*)"
     tmp1 <- loaded_chat %>%
         tidyr::extract(string, c("date", "time", "sender", "message"), regx, remove=FALSE)
     
     tmp1 <- filter(tmp1, !is.na(sender))
     
    # create nodes list
    nodes <- data.frame(select(tmp1, sender) %>% distinct()) 
    names(nodes) <- "id"

    # add in node colors, names 
    nodes$group <- nodes$id 
    nodes$label <- nodes$id

    #create number of messages sent for node size
    totals <- select(tmp1, sender, message) %>%
      mutate(ind = ifelse(grepl(input$word, message), 1, 0)) %>%
      group_by(sender) %>%
      summarise(sum = sum(ind))

  
    nodes$size <- pmax((totals$sum *100)/sum(totals$sum), 75/sum(totals$sum))
    nodes$title <- paste("<p style=\"color: black\">",totals$sum,"</p>")

    # create response matrix
    responses <- response_matrix_word(tmp1, 1, word = input$word)
    responses <-as.data.frame(responses)
    responses_t <- t(responses) #so that melt correctly picks up to and from
    responses_m <- melt(responses_t)
    names(responses_m) <- c("from","to", "number")

    responses_m
    
  })
}

shinyApp(ui, server)
}

Network comparison app

Network comparison app

Write the function that renders the network

library(reshape2)

Attaching package: <U+393C><U+3E31>reshape2<U+393C><U+3E32>

The following object is masked from <U+393C><U+3E31>package:tidyr<U+393C><U+3E32>:

    smiths
create_network_whatsapp <- function(file, word){
    # load chat  
    loaded_chat <- read.table(file,  
                                fill=TRUE, header=TRUE, quote="", sep="\n", encoding="UTF-8")
    names(loaded_chat) <- "string"
     
    # format the data and split into different columns
    regx <- "(\\d+/\\d+/\\d+),\\s+(\\d+:\\d+:\\d+ [A|P]M):\\s+(\\w+\\s*\\w+):\\s+(.*)"
    tmp <- loaded_chat %>%
         tidyr::extract(string, c("date", "time", "sender", "message"), regx, remove=FALSE)
     
     tmp <- filter(tmp, !is.na(sender))
     
    # create nodes list
    nodes <- data.frame(select(tmp, sender) %>% distinct()) 
    names(nodes) <- "id"
    # add in node colors, names 
    nodes$group <- nodes$id 
    nodes$label <- nodes$id
    #create number of messages sent for node size
    totals <- select(tmp, sender, message) %>%
      mutate(ind = ifelse(grepl(word, message), 1, 0)) %>%
      group_by(sender) %>%
      summarise(total_messages = sum(ind))
  
    nodes <- left_join(nodes, totals, by=c("id"="sender"))
    nodes$size <- pmax((nodes$total_messages *100)/sum(nodes$total_messages), 75/sum(nodes$total_messages))
    nodes$title <- paste("<p style=\"color: black\">",nodes$total_messages,"</p>")
    
    # create response matrix
    responses <- response_matrix_word(tmp, 1, word = word)
    responses <-as.data.frame(responses)
    responses_t <- t(responses) #so that melt correctly picks up to and from
    responses_m <- melt(responses_t)
    names(responses_m) <- c("from","to", "number")
    
    
    # format as network edges
    edges <- responses_m 
    edges$to <- as.character(edges$to) 
    edges$width <- (edges$number * 50)/sum(edges$number)
    edges$title <- paste("<p style=\"color:black\">",edges$number,"</p>")
    edges <- edges[edges$number > 0,]
    # render network 
    visNetwork(nodes, edges) %>%
      visPhysics( solver ='forceAtlas2Based')
  
  
  
  
}
create_network_whatsapp(file = "C:/Users/rober/Desktop/chat.txt", word = "hi")

Attaching package: <U+393C><U+3E31>magrittr<U+393C><U+3E32>

The following object is masked from <U+393C><U+3E31>package:purrr<U+393C><U+3E32>:

    set_names

The following object is masked from <U+393C><U+3E31>package:tidyr<U+393C><U+3E32>:

    extract

Use function to write cleaner shiny app

library(tidyverse)
library(shiny)
library(visNetwork)
library(shinythemes)
ui <- fluidPage(theme = shinytheme("cosmo"),
fluidRow(
    column(6,
      # render first network
      visNetworkOutput("network_1")
      
    ),
    
    column(6,
      # render first network
      visNetworkOutput("network_2")
      
    )
  ),
fluidRow(
    column(4,
      
      # file input 1
      fileInput("file_1", "Choose txt File 1",
        accept = c(
          "text/csv",
          "text/comma-separated-values,text/plain",
          ".csv",
          ".txt")
        ),
      tags$hr(),
   
      
      # create user input word box 
      textInput("word_1", "Word for first network", value = "hi ")
    ), 
    column(4),
    column(4,
      # file input 2
      fileInput("file_2", "Choose txt File 2",
      accept = c(
        "text/csv",
        "text/comma-separated-values,text/plain",
        ".csv",
        ".txt")),
      
      # create user input word box 
      textInput("word_2", "Word for second network", value = "hi ")
      )
    )
)
server <- function(input, output) {
    # Create Network 1
    output$network_1 <- renderVisNetwork({
    
    
    # input$file1 will be NULL initially. After the user selects
    # and uploads a file, it will be a data frame
    inFile_1 <- input$file_1
    if (is.null(inFile_1))
      return(NULL)
    
    create_network_whatsapp(inFile_1$datapath, input$word_1)
  })
  
      # Create Network 2
    output$network_2 <- renderVisNetwork({
    
    
    # input$file1 will be NULL initially. After the user selects
    # and uploads a file, it will be a data frame
    inFile_2 <- input$file_2
    if (is.null(inFile_2))
      return(NULL)
    
    create_network_whatsapp(inFile_2$datapath, input$word_2)
  })  
    
  
}
shinyApp(ui, server)

Listening on http://127.0.0.1:5917
LS0tDQp0aXRsZTogIlIgV2hhdHNhcHAgQW5hbHlzaXMiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpUaGlzIGNvZGUgc2V0cyBvdXQgaG93IHRvIHVwbG9hZCBhbmQgdGhlbiBhbmFseXNlIFdoYXRzYXBwIHRleHQgZGF0YSB1c2luZyBib3RoIGNoYXJ0cyBhbmQgbmV0d29ya3MuDQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KCJSQ3VybCIpDQpsaWJyYXJ5KCJkYXRhLnRhYmxlIikNCmxpYnJhcnkoc3RyaW5ncikNCg0KI3RhYiA9IHJlYWQuZGVsaW0oZ2V0VVJMKCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vcm9iZXJ0LXN0dXJyb2NrL3doYXRzYXBwLWFuYWx5c2lzL21hc3Rlci9jaGF0LnR4dCIpKQ0KI3dyaXRlLnRhYmxlKHRhYiwgZmlsZT0idGV4dC5jc3YiLHNlcD0iLCIsY29sLm5hbWVzPUZBTFNFLHJvdy5uYW1lcz1GQUxTRSkNCg0KDQoNCmNoYXQgPC0gcmVhZC50YWJsZSgiQzovVXNlcnMvcm9iZXIvRGVza3RvcC9jaGF0LnR4dCIsICBmaWxsPVRSVUUsIHF1b3RlPSIiLCBzZXA9IlxuIiwgZW5jb2Rpbmc9IlVURi04IikNCm5hbWVzKGNoYXQpIDwtICJzdHJpbmciDQoNCmBgYA0KDQpOb3cgd2UgbmVlZCB0byBsb29rIGF0IHRoZSBkYXRhIGFuZCBmb3JtYXQgaXQgYXBwcm9wZXJpYXRlbHkgDQoNCmBgYHtyfQ0KaGVhZChjaGF0KQ0KDQpgYGANCg0KU28gd2UgY2FuIHNlZSB3ZSBoYXZlIGEgZGF0ZSwgdGltZSwgc2VuZGVyLCBhbmQgbWVzc2FnZS4gDQoNClRoZSBmaXJzdCBvYnZpb3VzIGlzc3VlIGhlcmUgaXMgdGhhdCBvbmUgb2YgdGhlIHNlbmRlcnMgbmFtZXMgaGFzIGJlZW4gbWVzc2VkIHVwLiBXZSBjYW4gZml4IHRoaXMgdXNpbmcgdGhlIHJlZ2V4IGNvbW1hbmRzIGluIFIgDQoNCmBgYHtyfQ0KDQpjaGF0JHN0cmluZyA8LSBnc3ViKCIrMSAoMjE1KSAuKjogIiwgIkRlYmJpZSBCbGFpcjogIiwgY2hhdCRzdHJpbmcgKQ0KaGVhZChjaGF0JHN0cmluZykNCg0KDQoNCg0KYGBgDQoNCk5vdyB0aGF0IHdlIGhhdmUgbWFkZSB0aGF0IGNvcnJlY3Rpb24gd2UgbmVlZCB0byBzcGxpdCB0aGUgc3RyaW5nIG9mIHRleHQgaW50byB0aGUgaW5kaXZpZHVhbCBjb21wb25lbnRzIGlkZW50aWZpZWQgYWJvdmU6IA0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KDQpyZWd4IDwtICIoXFxkKy9cXGQrL1xcZCspLFxccysoXFxkKzpcXGQrOlxcZCsgW0F8UF1NKTpcXHMrKFxcdytcXHMqXFx3Kyk6XFxzKyguKikiDQoNCnRtcCA8LSBjaGF0ICU+JSANCiAgICB0aWR5cjo6ZXh0cmFjdChzdHJpbmcsIGMoImRhdGUiLCAidGltZSIsICJzZW5kZXIiLCAibWVzc2FnZSIpLCByZWd4LCByZW1vdmU9RkFMU0UpDQoNCg0KI2VsaW1pbmF0ZSBOQSByb3dzIChmb3Igbm93KQ0KdG1wIDwtIGZpbHRlcih0bXAsICFpcy5uYShzZW5kZXIpKQ0KDQpgYGANCg0KV2Ugbm93IGhhdmUgb3VyIGRlc2lyZWQgdmFyaWFibGVzLiBMZXRzIGJ1aWxkIHNvbWUgYmFzaWMgZnVuY3Rpb25hbGl0eSBsaWtlIHNlYXJjaA0KDQpgYGB7cn0NCg0KI3JlZ3VsYXIgZXhwcmVzc2lvbiBzZWFyY2gNCmdyZXAoInNleCIsIHRtcCRtZXNzYWdlLCB2YWx1ZT1UUlVFKQ0KDQoNCiNmdW5jdGlvbiB0aGF0IHJldHVybnMgb3RoZXIgY29sdW1ucyBvZiB0aGUgZGF0YSBhcyB3ZWxsDQp0ZXh0X3NlYXJjaCA8LSBmdW5jdGlvbih0ZXh0LCBkZil7DQogIHRtcCA8LSBkZg0KICB0bXBfaW5kZXggPC0gZ3JlcCh0ZXh0LCB0bXAkbWVzc2FnZSkNCiAgdG1wW2ModG1wX2luZGV4KSxjKCJzZW5kZXIiLCAibWVzc2FnZSIpXQ0KfQ0KDQp0ZXh0X3NlYXJjaCgic2V4IiwgdG1wKQ0KDQojZnVuY3Rpb24gdG8gc2VhcmNoIGFyb3VuZCBhIHNwZWNpZmljIGluc3RhbmNlIChtZXNzYWdlIGJlZm9yZSBhbmQgYWZ0ZXIpDQoNCiMgdGhpcyBmdW5jdGlvbiBnZW5lcmF0ZXMgYW5vdGhlciBmdW5jdGlvbiB0aGF0IGFsbG93cyB0aGUgdXNlciB0byBzZWxlY3Qgd2hpY2ggaW5zdGFuY2Ugb2YgYSB3b3JkLCBhbmQgdGhlIA0KIyBudW1iZXIgb2YgbGluZXMgYXJvdW5kIHRoYXQgd29yZCwgdGhleSB3YW50IHRvIHNlZS4gDQoNCmNvbnZfc2VhcmNoIDwtIGZ1bmN0aW9uKHRleHQsIGRmKXsgDQogIHRtcCA8LSBkZg0KICB0bXBfaW5kZXggPC0gZ3JlcCh0ZXh0LCB0bXAkbWVzc2FnZSkNCiAgDQogICNyZXR1cm4gbGluZXMNCiAgaW5kZXggPC0gdG1wX2luZGV4DQogIA0KICBmdW5jdGlvbihpbnN0YW5jZSwgbnVtX2xpbmVzKXsNCiAgICBpZiAobnVtX2xpbmVzICUlIDIgIT0wKXsiZXJyb3IsIG5lZWRzIGV2ZW4gbnVtYmVyIn0gZWxzZSB7DQogICAgDQogICAgaW5zdGFuY2UgPC0gaW5kZXhbaW5zdGFuY2VdDQogICAgc3RhcnQgPC0gaW5zdGFuY2UgLSBudW1fbGluZXMvMg0KICAgIGVuZCAgIDwtIGluc3RhbmNlICsgbnVtX2xpbmVzLzIgIA0KICAgIHRtcFtzdGFydDplbmQsIGMoInNlbmRlciIsICJtZXNzYWdlIildDQogICAgfSANCiAgfQ0KICANCiAgDQp9DQoNCnNleF9zZWFyY2ggPC0gY29udl9zZWFyY2goInNleCIsIHRtcCkNCnNleF9zZWFyY2goMiw2KQ0KDQpsaWJyYXJ5KHdvcmRjbG91ZCkNCg0KDQpgYGANCg0KDQoNCkdyZWF0LiBTbyB3ZSBidWlsdCBzb21lIGZ1bmN0aW9ucyB0aGF0IG1ha2UgaXQgZWFzeSB0byBzZWFyY2ggdGV4dC4gDQoNCkJ1dCBzZWFyY2hpbmcgaXNuJ3QgcmVhbGx5IHRoZSBiZXN0IHdheSB0byBnZXQgZGF0YSBhYm91dCB3aGF0IHBlb3BsZSB0YWxrZWQgYWJvdXQuIENoYXJ0cyBvbiB0aGUgb3RoZXIgaGFuZCBhcmUgYXdlc29tZS4gDQoNCkkgc3RhcnQgYnkgYnVpbGRpbmcgYSBzaW1wbGUgZnJlcXVlbmN5IGNoYXJ0IG9mIGhvdyBvZnRlbiBhIGdpdmVuIHdvcmsgd2FzIHNhaWQNCg0KDQpgYGB7cn0NCg0KIyBDcmVhdGUgYSBzaW5nbGUgYmxvY2sgb2YgdGV4dCB3aXRoIGFsbCB0aGUgd29yZHMNCg0KdGVzdCA8LSB1bmxpc3QodG1wJG1lc3NhZ2VbdG1wJHNlbmRlciA9PSAiTGlhbSBLaXJ3aW4iXSkNCnRlc3QgPC0gdW5saXN0KHRtcCRtZXNzYWdlKQ0KdGVzdCA8LSBwYXN0ZSh0ZXN0LCBzZXA9IiIsY29sbGFwc2UgPSIgIikNCg0KIyBsb2FkIHJlcXVpcmVkIHBhY2thZ2VzDQoNCmxpYnJhcnkodG0pDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeSh4dGFibGUpDQoNCmRvY3MgPC0gQ29ycHVzKFZlY3RvclNvdXJjZSh0ZXN0KSkgJT4lDQogIHRtX21hcChyZW1vdmVQdW5jdHVhdGlvbikgJT4lDQogIHRtX21hcChyZW1vdmVOdW1iZXJzKSAlPiUNCiAgdG1fbWFwKHRvbG93ZXIpICAlPiUNCiAgdG1fbWFwKHJlbW92ZVdvcmRzLCBzdG9wd29yZHMoImVuZ2xpc2giKSkgJT4lDQogIHRtX21hcChzdHJpcFdoaXRlc3BhY2UpICU+JQ0KICB0bV9tYXAoUGxhaW5UZXh0RG9jdW1lbnQpDQoNCnRkbSA8LSBUZXJtRG9jdW1lbnRNYXRyaXgoZG9jcykgJT4lDQogIGFzLm1hdHJpeCgpDQoNCnRkbSA8LSBhcy5tYXRyaXgodGRtWywxXSkNCnRkbSA8LSBhcy5tYXRyaXgodGRtW29yZGVyKHRkbSwgZGVjcmVhc2luZyA9IFRSVUUpLF0pDQojdGRtIDwtIGFzLm1hdHJpeCh0ZG1bMTA6MTc1NDYsXSkNCiN0ZG0gPC0gdGRtW29yZGVyKHRkbSwgZGVjcmVhc2luZyA9IFRSVUUpLF0NCg0KDQoNCndvcmRjbG91ZChyb3cubmFtZXModGRtKSwgdGRtLCBtaW4uZnJlcSA9IDM1LCBzY2FsZT1jKDUsIC4yKSwgcmFuZG9tLm9yZGVyID0gRkFMU0UsIHJhbmRvbS5jb2xvciA9IEZBTFNFLCBjb2xvcnM9IGMoImluZGlhbnJlZDEiLCJpbmRpYW5yZWQyIiwiaW5kaWFucmVkMyIsImluZGlhbnJlZCIpKQ0KDQoNCg0KDQojTm93IHdlIGNyZWF0ZSBhIHdvcmRjbG91ZCBmdW5jdGlvbiANCg0KV0Ffd29yZGNsb3VkIDwtIGZ1bmN0aW9uKHNlbmRlciwgZGYsIG1pbi5mcmVxKXsNCiAgDQogICNyZXF1aXJlZCBwYWNrYWdlcw0KICAjcmVxdWlyZSh0bSkNCiAgI3JlcXVpcmUoZHBseXIpDQogICNyZXF1aXJlKHh0YWJsZSkNCiAgI3JlcXVpcmUod29yZGNsb3VkKQ0KICAjcmVxdWlyZShzdHJpbmdyKQ0KICANCiAgI3NldCBmdW5jdGlvbg0KICB0bXAgPC0gdW5saXN0KGRmJG1lc3NhZ2VbZGYkc2VuZGVyID09IHNlbmRlcl0pDQogIHRtcCA8LSBwYXN0ZSh0bXAsIHNlcD0iIixjb2xsYXBzZSA9IiIpDQogIA0KICAjZWxpbWluYXRlIGFsbCBub24gYWxwaGEgbnVtYmVyaWMNCiAgdG1wIDwtIHN0cl9yZXBsYWNlX2FsbCh0bXAsICJbXmEtekEtWjAtOV0iLCIgIikNCg0KICANCiAgI2NyZWF0ZSB0ZXJtIGRvY3VtZW50IG1hdHJpeCBhbmQgZm9ybWF0IGl0DQogIHRtcF9kb2NzIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UodG1wKSkgJT4lDQogIHRtX21hcChyZW1vdmVQdW5jdHVhdGlvbikgJT4lDQogIHRtX21hcChyZW1vdmVOdW1iZXJzKSAlPiUNCiAgdG1fbWFwKHRvbG93ZXIpICAlPiUNCiAgdG1fbWFwKHJlbW92ZVdvcmRzLCBzdG9wd29yZHMoImVuZ2xpc2giKSkgJT4lDQogIHRtX21hcChyZW1vdmVXb3JkcywiaW1hZ2UiKSAlPiUNCiAgdG1fbWFwKHN0cmlwV2hpdGVzcGFjZSkgJT4lDQogIHRtX21hcChQbGFpblRleHREb2N1bWVudCkNCiAgDQogIHRtcF90ZG0gPC0gVGVybURvY3VtZW50TWF0cml4KHRtcF9kb2NzKSAlPiUNCiAgYXMubWF0cml4KCkNCiAgDQogIHRtcF90ZG0gPC0gYXMubWF0cml4KHRtcF90ZG1bLDFdKQ0KICB0bXBfdGRtIDwtIGFzLm1hdHJpeCh0bXBfdGRtW29yZGVyKHRtcF90ZG0sIGRlY3JlYXNpbmcgPSBUUlVFKSxdKQ0KICANCiAgI2NyZWF0ZSB3b3JkY2xvdWQNCiAgbGF5b3V0KG1hdHJpeChjKDEsMiksIG5yb3cgPSAyKSwgaGVpZ2h0cyA9IGMoMSwyKSkNCiAgcGFyKG1hciA9IHJlcCgwLDQpKQ0KICBwbG90Lm5ldygpDQogIHRleHQoeD0wLjUsIHk9MC41LCBzZW5kZXIpDQogIA0KICANCiAgd29yZGNsb3VkKHJvdy5uYW1lcyh0bXBfdGRtKSwgdG1wX3RkbSwgDQogICAgICAgICAgICBtaW4uZnJlcSA9IG1pbi5mcmVxLCANCiAgICAgICAgICAgIHNjYWxlPWMoMiwgLjEpLCANCiAgICAgICAgICAgIHJhbmRvbS5vcmRlciA9IEZBTFNFLCANCiAgICAgICAgICAgIHJhbmRvbS5jb2xvciA9IEZBTFNFLCAgDQogICAgICAgICAgICBjb2xvcnM9IGMoImluZGlhbnJlZDEiLCJpbmRpYW5yZWQyIiwiaW5kaWFucmVkMyIsImluZGlhbnJlZCIpKQ0KDQoNCiAgDQp9DQoNCg0KV0Ffd29yZGNsb3VkKHNlbmRlciA9ICJMaWFtIEtpcndpbiIsIGRmID0gdG1wLCBtaW4uZnJlcSA9IDE1KQ0KDQpmbGF0X25hbWVzIDwtIGxpc3QoIkxpYW0gS2lyd2luIiwgIklzYWJlbCBMYWNoZW5hdWVyIiwgIlJvYmVydCIsICJEZWJiaWUgQmxhaXIiLCAiRWxpemFiZXRoIFN0b25lIikNCg0KbGFwcGx5KGZsYXRfbmFtZXMsIGZ1bmN0aW9uKHgpIFdBX3dvcmRjbG91ZCh4LCBkZiA9IHRtcCwgbWluLmZyZXEgPSAyNSkpDQoNCmBgYA0KDQoNCkFub3RoZXIgcG90ZW50aWFsbHkgaW50ZXJlc3RpbmcgaWRlYSBpcyB0byBkbyBhIHdvcmRjbG91ZCBvZiB3b3JkcyB0aGF0IHBlb3BsZSB1c2UgbW9yZSB0aGFuIHRoZSBhdmVyYWdlLiBUaGlzIHdvdWxkIGludm9sdmUgY2FsY3VsYXRpbmcgdHdvIGRhdGEuZnJhbWVzL21hdHJpY2llcyB3aXRoIHdvcmRzIGFuZCBmcmVxdWVuY2llcy4gQW5kIHRoZW4gc3VidHJhY3RpbmcgdGhlIGluZGl2aWR1YWwgd29yZHMgZnJvbSB0aGUgYXZlcmFnZS4gDQoNCg0KU3RlcCAxOiANCmBgYHtyfQ0KDQojY3JlYXRlIGEgZnVuY3Rpb24gdGhhdCBjcmVhdGVzIGEgdGRtIA0KDQp0ZG1fY3JlYXRvciA8LSBmdW5jdGlvbihzZW5kZXI9ImFsbCIsIGRmKXsNCiAgDQogICNzZXQgZnVuY3Rpb24NCiAgaWYoc2VuZGVyICE9ICJhbGwiKXt0bXAgPC0gdW5saXN0KGRmJG1lc3NhZ2VbZGYkc2VuZGVyID09IHNlbmRlcl0pfSBlbHNlIHt0bXAgPC0gdW5saXN0KGRmJG1lc3NhZ2UpfQ0KICB0bXAgPC0gcGFzdGUodG1wLCBzZXA9IiIsY29sbGFwc2UgPSIiKQ0KICANCiAgI2VsaW1pbmF0ZSBhbGwgbm9uIGFscGhhIG51bWJlcmljDQogIHRtcCA8LSBzdHJfcmVwbGFjZV9hbGwodG1wLCAiW15hLXpBLVowLTldIiwiICIpDQoNCiAgDQogICNjcmVhdGUgdGVybSBkb2N1bWVudCBtYXRyaXggYW5kIGZvcm1hdCBpdA0KICB0bXBfZG9jcyA8LSBDb3JwdXMoVmVjdG9yU291cmNlKHRtcCkpICU+JQ0KICB0bV9tYXAocmVtb3ZlUHVuY3R1YXRpb24pICU+JQ0KICB0bV9tYXAocmVtb3ZlTnVtYmVycykgJT4lDQogIHRtX21hcCh0b2xvd2VyKSAgJT4lDQogIHRtX21hcChyZW1vdmVXb3Jkcywgc3RvcHdvcmRzKCJlbmdsaXNoIikpICU+JQ0KICB0bV9tYXAocmVtb3ZlV29yZHMsImltYWdlIikgJT4lDQogIHRtX21hcChzdHJpcFdoaXRlc3BhY2UpICU+JQ0KICB0bV9tYXAoUGxhaW5UZXh0RG9jdW1lbnQpDQogIA0KICB0bXBfdGRtIDwtIFRlcm1Eb2N1bWVudE1hdHJpeCh0bXBfZG9jcykgJT4lDQogIGFzLm1hdHJpeCgpDQogIA0KICB0bXBfdGRtIDwtIGFzLm1hdHJpeCh0bXBfdGRtWywxXSkNCiAgYXMubWF0cml4KHRtcF90ZG1bb3JkZXIodG1wX3RkbSwgZGVjcmVhc2luZyA9IFRSVUUpLF0pDQp9DQoNCg0KDQp3b3JkX2RmIDwtIGZ1bmN0aW9uKG1hdHIpew0KICBkYXRhLmZyYW1lKHdvcmQgPSByb3cubmFtZXMobWF0ciksIGZyZXEgPSBtYXRyKQ0KfQ0KDQojY3JlYXRlIGRhdGEuZnJhbWVzIHRvIGNvbXBhcmUNCmlzYWJlbCA8LSB0ZG1fY3JlYXRvcihzZW5kZXIgPSAiSXNhYmVsIExhY2hlbmF1ZXIiLCBkZiA9IHRtcCkNCmxpYW0gPC0gdGRtX2NyZWF0b3Ioc2VuZGVyID0gIkxpYW0gS2lyd2luIiwgZGYgPSB0bXApDQphbGwgPC0gdGRtX2NyZWF0b3IoZGYgPSB0bXApDQoNCmlzYWJlbCA8LSB3b3JkX2RmKGlzYWJlbCkNCmxpYW0gPC0gd29yZF9kZihsaWFtKQ0KYWxsIDwtIHdvcmRfZGYoYWxsKQ0KDQp0IDwtIGxlZnRfam9pbihsaWFtLCBhbGwsIGJ5ID0gIndvcmQiKQ0KdCA8LSBsZWZ0X2pvaW4oaXNhYmVsLCBhbGwsIGJ5ID0gIndvcmQiKQ0KDQojaWRlbnRpZnkgd29yZHMgdGhhdCBsaWFtIHNheXMgcmVsYXRpdmVseSBtb3JlIHRoYW4gb3RoZXJzDQoNCnQkZGlmZiA8LSB0JGZyZXEueCAtIHQkZnJlcS55LzUNCg0KDQp0ICU+JSBhcnJhbmdlKGRlc2MoZGlmZikpICU+JSBoZWFkKCkNCg0KI2NvbnRyb2wgYWxzbyBmb3IgZnJlcXVlbmN5IHRoYXQgdGhlIHdvcmQgYXBwZWFycyBpbiB0aGUgZ2VuZXJhbCBncm91cCBjaGF0IA0KDQp0IDwtIHRbdCRmcmVxLnggPD0gdCRmcmVxLnksXQ0KdCRkaWZmMiA8LSAodCRmcmVxLnggLSB0JGZyZXEueS81KS90JGZyZXEueQ0KDQoNCnQgJT4lIGFycmFuZ2UoZGVzYyhkaWZmMikpICU+JSBoZWFkKCkNCg0KI2NyZWF0ZSBhIHdvcmQgY2xvdWQgb2YgbW9zdCB1bmlxdWUgd29yZHMNCg0KdDIgPC0gdCAlPiUgZmlsdGVyKGRpZmY+MCkNCg0Kd29yZGNsb3VkKHQyJHdvcmQsIHQyJGRpZmYsDQogICAgICAgICAgICBzY2FsZT1jKDMsIC4xKSwgDQogICAgICAgICAgICByYW5kb20ub3JkZXIgPSBGQUxTRSwgDQogICAgICAgICAgICByYW5kb20uY29sb3IgPSBGQUxTRSwgIA0KICAgICAgICAgICAgY29sb3JzPSBjKCJpbmRpYW5yZWQxIiwiaW5kaWFucmVkMiIsImluZGlhbnJlZDMiLCJpbmRpYW5yZWQiKSkNCg0KIyB1c2UgYWx0ZXJuYXRpdmUgbWV0aG9kLCBidXQgb25seSB1c2Ugd29yZHMgdGhhdCBhcHBlYXIgYXQgbGVhc3QgMyB0aW1lcw0KdDMgPC0gdCAlPiUgZmlsdGVyKGRpZmYyPjAgJiBmcmVxLnggPjMpDQoNCg0Kd29yZGNsb3VkKHQzJHdvcmQsIHQzJGRpZmYyLA0KICAgICAgICAgICAgc2NhbGU9YygzLCAuMSksIA0KICAgICAgICAgICAgbWF4LndvcmQgPSAxMDAsDQogICAgICAgICAgICByYW5kb20ub3JkZXIgPSBGQUxTRSwgDQogICAgICAgICAgICByYW5kb20uY29sb3IgPSBGQUxTRSwgIA0KICAgICAgICAgICAgY29sb3JzPSBjKCJpbmRpYW5yZWQxIiwiaW5kaWFucmVkMiIsImluZGlhbnJlZDMiLCJpbmRpYW5yZWQiKSkNCg0KYGBgDQoNCg0KDQpgYGB7cn0NCg0KIyBGdW5jdGlvbiB0aGF0IGNyZWF0ZXMgYSB1bmlxdWUgd29yZCBjbG91ZCBieSBwZXJzb24gDQoNCnVuaXF1ZV93b3JkY2xvdWQgPC0gZnVuY3Rpb24oZGYsIHNlbmRlciwgdHlwZSl7DQogIA0KICAjdG90YWwgc2VuZGVycw0KICB0b3Rfc2VuZGVycyA8LSBsZW5ndGgodW5pcXVlKGRmJHNlbmRlcikpDQogIA0KICAjY3JlYXRlIHRkbQ0KICBwZXJzb24gPC0gd29yZF9kZih0ZG1fY3JlYXRvcihzZW5kZXIgPSBzZW5kZXIsIGRmID0gdG1wKSkNCiAgYWxsIDwtIHdvcmRfZGYodGRtX2NyZWF0b3IoZGYgPSB0bXApKQ0KICANCiAgdCA8LSBsZWZ0X2pvaW4ocGVyc29uLCBhbGwsIGJ5ID0gIndvcmQiKQ0KDQogICNpZGVudGlmeSB3b3JkcyB0aGF0IGxpYW0gc2F5cyByZWxhdGl2ZWx5IG1vcmUgdGhhbiBvdGhlcnMNCiAgDQogIHQkZGlmZiA8LSB0JGZyZXEueCAtIHQkZnJlcS55L3RvdF9zZW5kZXJzDQogIA0KICAjY29udHJvbCBhbHNvIGZvciBmcmVxdWVuY3kgdGhhdCB0aGUgd29yZCBhcHBlYXJzIGluIHRoZSBnZW5lcmFsIGdyb3VwIGNoYXQgDQogIA0KICB0IDwtIHRbdCRmcmVxLnggPD0gdCRmcmVxLnksXQ0KICB0JGRpZmYyIDwtICh0JGZyZXEueCAtIHQkZnJlcS55L3RvdF9zZW5kZXJzKS90JGZyZXEueQ0KICANCiAgI2NyZWF0ZSBhIHdvcmQgY2xvdWQgb2YgbW9zdCB1bmlxdWUgd29yZHMNCiAgDQogIHQyIDwtIHQgJT4lIGZpbHRlcihkaWZmPjApDQogIHQzIDwtIHQgJT4lIGZpbHRlcihkaWZmMj4wICYgZnJlcS54ID4zKQ0KDQogIA0KICANCiAgaWYgKHR5cGUgPT0gMSl7DQogIHdvcmRjbG91ZCh0MiR3b3JkLCB0MiRkaWZmLA0KICAgICAgICAgICAgICBzY2FsZT1jKDMsIC4xKSwgDQogICAgICAgICAgICAgIHJhbmRvbS5vcmRlciA9IEZBTFNFLCANCiAgICAgICAgICAgICAgcmFuZG9tLmNvbG9yID0gRkFMU0UsICANCiAgICAgICAgICAgICAgY29sb3JzPSBjKCJpbmRpYW5yZWQxIiwiaW5kaWFucmVkMiIsImluZGlhbnJlZDMiLCJpbmRpYW5yZWQiKSl9IA0KICANCiAgZWxzZSBpZiAodHlwZSA9PTIpew0KICB3b3JkY2xvdWQodDMkd29yZCwgdDMkZGlmZjIsDQogICAgICAgICAgICBzY2FsZT1jKDMsIC4xKSwgDQogICAgICAgICAgICByYW5kb20ub3JkZXIgPSBGQUxTRSwgDQogICAgICAgICAgICByYW5kb20uY29sb3IgPSBGQUxTRSwgIA0KICAgICAgICAgICAgY29sb3JzPSBjKCJpbmRpYW5yZWQxIiwiaW5kaWFucmVkMiIsImluZGlhbnJlZDMiLCJpbmRpYW5yZWQiKSkNCiAgfSBlbHNlIHtzdG9wKCdpbnZhbGlkIHR5cGUgc2VsZWN0ZWQnKX0NCiAgDQogICAgDQogIA0KfQ0KDQp1bmlxdWVfd29yZGNsb3VkKGRmID0gdG1wLCBzZW5kZXIgPSAiRWxpemFiZXRoIFN0b25lIiwgdHlwZSA9IDIpDQp1bmlxdWVfd29yZGNsb3VkKGRmID0gdG1wLCBzZW5kZXIgPSAiUm9iZXJ0IiwgdHlwZSA9IDIpDQoNCg0KDQoNCg0KDQpmbGF0X25hbWVzIDwtIGxpc3QoIkxpYW0gS2lyd2luIiwgIklzYWJlbCBMYWNoZW5hdWVyIiwgIlJvYmVydCIsICJEZWJiaWUgQmxhaXIiLCAiRWxpemFiZXRoIFN0b25lIikNCg0KbGFwcGx5KGZsYXRfbmFtZXMsIGZ1bmN0aW9uKHgpIHVuaXF1ZV93b3JkY2xvdWQoc2VuZGVyID0geCwgZGYgPSB0bXAsIHR5cGUgPSAyKSkNCg0KDQpgYGANCg0KIyBXb3JkcyBzYWlkIG92ZXIgdGltZQ0KDQpTbyBub3cgSSBuZWVkIHRvIHJlcGxpY2F0ZSBzb21lIG9mIHRoZSB3b3JrIEkgZGlkIGVhcmxpZXIsIG5hbWVseSBwbG90dGluZyB0aGUgZnJlcXVlbmN5IG9mIHdvcmRzIG92ZXIgdGltZQ0KDQoNCmBgYHtyfQ0KDQoNCiNzdGVwIDE6DQoNCiNjb3VudCB0aGUgbnVtYmVyIG9mIHRpbWVzIGEgd29yZCBhcHBlYXJzIGJ5IGRhdGUNCnRtcCAlPiUgZ3JvdXBfYnkoZGF0ZSkgJT4lIHN1bW1hcmlzZShudW1iZXIgPSBuKCkpDQoNCg0KDQoNCg0KDQpgYGANCg0KDQojd2hvIHRhbGtzIHRvIHdobyB0aGUgbW9zdA0KDQoNCmBgYHtyfQ0KDQoNCg0KI3dyaXRlIGEgZnVuY3Rpb24gdGhhdCBsb29rcyBhdCBtb3N0IGZyZXF1ZW50IHJlcG9uZGVycw0KDQoNCnJlc3BvbnNlX3N1bW1hcnkgPC0gZnVuY3Rpb24oZGYsIHBlcnNvbiwgdHlwZSl7DQpsaWJyYXJ5KHNjYWxlcykNCiNzZWxlY3Qgc2VuZGVyIA0KICB0bXAgPC0gZGYgDQogIHRtcCRpbmRpY2F0b3IgPC0gMCANCiAgdG1wW3RtcCRzZW5kZXIgPT0gcGVyc29uLF0kaW5kaWNhdG9yIDwtIDEgDQogIHRtcCRpbmQgPC0gbGFnKHRtcCRpbmRpY2F0b3IpDQoNCiAgI2NhbGN1bGF0ZSB0b3RhbCBtZXNzYWdlcyBieSBzZW5kZXIgDQogIHRtcCA8LSB0bXAgJT4lIGdyb3VwX2J5KHNlbmRlcikgJT4lDQogIG11dGF0ZSh0b3RhbF9tZXNzYWdlcyA9IG4oKSkgDQogIHRtcA0KICANCiAgI2NyZWF0ZSBzdGF0aXN0aWNzDQogIGlmICh0eXBlID09IDEpeyB0bXAgJT4lIGdyb3VwX2J5KHNlbmRlcikgJT4lIA0KICAgICAgZmlsdGVyKGluZCA9PSAxKSAlPiUgDQogICAgICBzdW1tYXJpc2UodG90YWxfcmVzcG9uc2VzID0gbigpKQ0KICANCiAgfSBlbHNlIGlmICh0eXBlID09IDIpeyB0bXAgJT4lIGdyb3VwX2J5KHNlbmRlcikgJT4lIA0KICAgICAgZmlsdGVyKGluZCA9PSAxKSAlPiUgDQogICAgICBtdXRhdGUodG90YWxfcmVzcG9uc2VzX3RvX3NlbmRlciA9IG4oKSkgJT4lIA0KICAgICAgbXV0YXRlKGRvbmUgPSB0b3RhbF9yZXNwb25zZXNfdG9fc2VuZGVyL3RvdGFsX21lc3NhZ2VzKSAlPiUgDQogICAgICBzdW1tYXJpc2UoIiUgb2YgYWxsIG1lc3NhZ2VzIG1hZGUgaW4gcmVzcG9uc2UgdG8gc2VuZGVyIiA9IHBlcmNlbnQobWVhbihkb25lKSkpfSB9DQoNCg0KcmVzcG9uc2Vfc3VtbWFyeSh0bXAsICJMaWFtIEtpcndpbiIsIHR5cGUgPSAxKQ0KDQoNCiMgQ3JlYXRlIGEgcmVzcG9uc2UgbWF0cml4DQoNCg0KcmVzcG9uc2VfbWF0cml4IDwtIGZ1bmN0aW9uKGRmLCB0eXBlKXsNCg0Kc2VuZGVycyA8LSByZXNwb25zZV9zdW1tYXJ5KHRtcCwgZmxhdF9uYW1lc1tbMV1dLCB0eXBlID0gdHlwZSkkc2VuZGVyDQoNCg0KcmVzcG9uc2VzX3RvdGFsIDwtIGNiaW5kKGFzLmRhdGEuZnJhbWUobGFwcGx5KHNlbmRlcnMsIGZ1bmN0aW9uKHgpDQpyZXNwb25zZV9zdW1tYXJ5KGRmLCB4LCB0eXBlID0gdHlwZSlbWzJdXSkpKSANCm5hbWVzKHJlc3BvbnNlc190b3RhbCkgPC0gc2VuZGVycyANCnJvdy5uYW1lcyhyZXNwb25zZXNfdG90YWwpIDwtIHNlbmRlcnMgDQpyZXNwb25zZXNfdG90YWwNCg0KDQp9DQoNCnJlc3BvbnNlX21hdHJpeCh0bXAsIDEpDQoNCiNjaGVjayBob3cgZXF1YWxseSBwZW9wbGUgcmVzcG9uZCB0byBlYWNoIG90aGVyDQoNCm1hdDEgPC0gYXMubWF0cml4KHJlc3BvbnNlX21hdHJpeCh0bXAsIDEpKSAjIGhvdyBvZnRlbiB4IHJlc3BvbmRlZCB0byB5IA0KbWF0MiA8LSB0KG1hdDEpICMgaG93IG9mdGVuIHkgcmVzcG9uZGVkIHRvIHgNCg0KI3NvIHdoYXQgdGhpcyBtZWFucyBpcyB0aGF0IG1hdDFbMSwyXSAtIG1hdDJbMSwyXSBpcyBob3cgb2Z0ZW4gTGl6emllIHJlcGxpZWQgdG8gIERlYmJpZSAtIGhvdyBvZnRlbiBEZWJiaWUgcmVwbGllZCB0byBMaXp6aWUNCg0KbWF0MSANCm1hdDINCg0KIyB0aGUgcmVzdWx0cyBzaG93IHRoYXQgcGVvcGxlIGluIG91ciBjb252ZXJzYXRpb24gYXJlIHF1aXRlIGVxdWFsLiBXaGljaCBpcyB3aGF0IHdlJ2QgZXhwZWN0IGluIGNvbnZlcnNhdGlvbnMgd2hlcmUgdHdvIHBlb3BsZSBhcmUgbW9zdCBpbXBvcnRhbnQvbm8gb25lIHBlcnNvbiBpcyBhdm9pZGluZyB0aGUgb3RoZXIuDQoNCihtYXQxIC0gbWF0MikNCg0KDQojIHRvdGFsIG1lc3NhZ2VzIHBlb3BsZSBzZW50DQoNCmxhcHBseShyZXNwb25zZV9tYXRyaXgodG1wLDEpLCBzdW0pDQoNCiMgZG8gdGhpcyBieSB3b3JkIGNvdW50IA0KYGBgDQoNCg0KDQoNCg0KIyBEdXBsaWNhdGUgdGhlIGZ1bmN0aW9ucyBhYm92ZSwgYnV0IGFwcGx5IGl0IHRvIGluZGl2aWR1YWwgd29yZHMNCg0KDQpgYGB7cn0NCg0KDQoNCiN3cml0ZSBhIGZ1bmN0aW9uIHRoYXQgbG9va3MgYXQgbW9zdCBmcmVxdWVudCByZXBvbmRlcnMNCg0KDQpyZXNwb25zZV9zdW1tYXJ5X3dvcmQgPC0gZnVuY3Rpb24oZGYsIHBlcnNvbiwgdHlwZSwgd29yZCl7DQpsaWJyYXJ5KHNjYWxlcykNCmxpYnJhcnkobWFncml0dHIpDQojc2VsZWN0IHNlbmRlciANCiAgdG1wIDwtIGRmIA0KICB0bXAkaW5kaWNhdG9yIDwtIDAgDQogIGlmIChsZW5ndGgodG1wW3RtcCRzZW5kZXIgPT0gcGVyc29uICYgZ3JlcGwod29yZCwgdG1wJG1lc3NhZ2UpLF0kaW5kaWNhdG9yKSA+IDApew0KICAgIHRtcFt0bXAkc2VuZGVyID09IHBlcnNvbiAmIGdyZXBsKHdvcmQsIHRtcCRtZXNzYWdlKSxdJGluZGljYXRvciA8LSAxIA0KICB9IGVsc2UgeyANCiAgICB0bXAkaW5kaWNhdG9yIDwtIDANCiAgfQ0KICB0bXAkaW5kaWNhdG9yIDwtIGxhZyh0bXAkaW5kaWNhdG9yKQ0KICB0bXAgJTw+JSBtdXRhdGUoaW5kaWNhdG9yID0gaWZlbHNlKGlzLm5hKGluZGljYXRvciksIDAsIGluZGljYXRvcikpDQoNCiNjYWxjdWxhdGUgdG90YWwgbWVzc2FnZXMgYnkgc2VuZGVyIA0KICB0bXAgPC0gdG1wICU+JSBncm91cF9ieShzZW5kZXIpICU+JQ0KICAgIG11dGF0ZSh0b3RhbF9tZXNzYWdlcyA9IG4oKSkgDQogIA0KDQppZiAodHlwZSA9PSAxKXsgdG1wICU+JSBncm91cF9ieShzZW5kZXIpICU+JSBzdW1tYXJpc2UodG90YWxfcmVzcG9uc2VzID0gc3VtKG5hLm9taXQoaW5kaWNhdG9yKSkpDQoNCn0gZWxzZSBpZiAodHlwZSA9PSAyKXt0bXAgJT4lIGdyb3VwX2J5KHNlbmRlcikgJT4lDQogICAgbXV0YXRlKHRvdGFsX3Jlc3BvbnNlc190b19zZW5kZXIgPSBzdW0obmEub21pdChpbmRpY2F0b3IpKSkgJT4lDQogICAgbXV0YXRlKGRvbmUgPSB0b3RhbF9yZXNwb25zZXNfdG9fc2VuZGVyL3RvdGFsX21lc3NhZ2VzKSAlPiUgDQogICAgc3VtbWFyaXNlKCIlIG9mIGFsbCBtZXNzYWdlcyBtYWRlIGluIHJlc3BvbnNlIHRvIHNlbmRlciIgPSBwZXJjZW50KG1lYW4oZG9uZSkpKX0gfQ0KDQoNCg0KcmVzcG9uc2Vfc3VtbWFyeV93b3JkKHRtcCwgIlJvYmVydCIsIHR5cGUgPSAxLCB3b3JkPSJzZXgiKQ0KDQoNCg0KDQoNCg0KIyBDcmVhdGUgYSByZXNwb25zZSBtYXRyaXgNCg0KDQpyZXNwb25zZV9tYXRyaXhfd29yZCA8LSBmdW5jdGlvbihkZiwgdHlwZSwgd29yZCl7DQpzZW5kZXJzIDwtIHJlc3BvbnNlX3N1bW1hcnkoZGYsIGRmJHNlbmRlcltbMV1dLCB0eXBlID0gMSkkc2VuZGVyDQoNCg0KcmVzcG9uc2VzX3RvdGFsIDwtIGNiaW5kKGFzLmRhdGEuZnJhbWUobGFwcGx5KHNlbmRlcnMsIGZ1bmN0aW9uKHgpDQpyZXNwb25zZV9zdW1tYXJ5X3dvcmQoZGYsIHgsIHR5cGUgPSB0eXBlLCB3b3JkID0gd29yZClbLDJdKSkpIA0KbmFtZXMocmVzcG9uc2VzX3RvdGFsKSA8LSBzZW5kZXJzIA0Kcm93Lm5hbWVzKHJlc3BvbnNlc190b3RhbCkgPC0gc2VuZGVycyANCnJlc3BvbnNlc190b3RhbA0KDQoNCn0NCg0KcmVzcG9uc2VfbWF0cml4X3dvcmQodG1wLCAxLCB3b3JkID0gImxvbCIpDQoNCg0KDQpgYGANCg0KDQoNCg0KDQojIE5leHQ6IHdyaXRlIHNvbWUgb2YgdGhlIGZ1bmN0aW9ucyB1c2luZyBTRQ0KDQpgYGB7cn0NCg0KbGlicmFyeShsdWJyaWRhdGUpDQoNCiNzZWxlY3QgZ3JvdXBzIHVzaW5nZSBTRQ0KDQpmcmVxX3Bsb3QgPC0gZnVuY3Rpb24oZGYsIHdvcmQsIHYxLCB2Mil7DQoNCiBkZiAlPiUgbXV0YXRlKGRhdGUgPSBtZHkoZGF0ZSkpICU+JQ0KICBncm91cF9ieV8odjEsIHYyKSAlPiUNCiAgZmlsdGVyKGdyZXBsKHdvcmQsIG1lc3NhZ2UpKSAlPiUgIA0KICBzdW1tYXJpc2UoY291bnQgPSBuKCkpICU+JQ0KICBnZ3Bsb3QoYWVzKHggPSBkYXRlLCB5ID0gY291bnQsIGNvbG9yID0gc2VuZGVyKSkgKyBnZW9tX3BvaW50KCkgKyB5bGltKDAsTkEpICsgdGhlbWVfYncoKSB9DQoNCg0KZnJlcV9wbG90KHRtcCwgIi4iLCB2MSA9ICJzZW5kZXIiLCB2MiA9ICJkYXRlIikNCg0KI3N1bW1hcnkgdGFibGUgb2YgdHdvIHZhcmlhYmxlDQoNCnR3X3RhYiA8LSBmdW5jdGlvbihkZiwgdjEsIHYyKXsNCg0KdG1wIDwtIGRmDQoNCnRtcCAlPiUgZ3JvdXBfYnlfKHYxLCB2MikgJT4lIA0KICBtdXRhdGUodG90PW4oKSkgJT4lIA0KICB1bmdyb3VwKCkgJT4lIA0KICBncm91cF9ieV8odjEpICU+JSANCiAgbXV0YXRlKHBlcmMgPSB0b3QvbigpKSAlPiUgDQogIHVuZ3JvdXAoKSAlPiUgZ3JvdXBfYnlfKHYxLCB2MikgJT4lIA0KICBzdW1tYXJpc2UoZW5kID0gbWVhbihwZXJjKSkgJT4lIGRjYXN0KHBhc3RlKHYxLCAnficsIHYyKSwgdmFsdWUudmFyID0gImVuZCIpDQoNCn0NCg0KIyBwbG90IHNoYXJlIG9mIGNvbnZlcnNhdGlvbiBvdmVyIHRpbWUgDQp0d190YWIodG1wLCAiZGF0ZSIsICJzZW5kZXIiKSAlPiUNCiAgbXV0YXRlKGRhdGUgPSBtZHkoZGF0ZSkpICU+JSANCiAgbWVsdChpZC52YXJzPSJkYXRlIikgJT4lIA0KICBnZ3Bsb3QoYWVzKHggPSBkYXRlLCB5ID0gdmFsdWUsIGNvbG9yID0gdmFyaWFibGUsIGZpbGwgPSB2YXJpYWJsZSkpICsgZ2VvbV9jb2woKQ0KDQoNCg0KDQpgYGANCg0KDQoNCg0KDQoNCg0KDQojIE5leHQ6IHR1cm4gdGhlIHJlc3BvbnNlIG1hdHJpeCBpbnRvIGEgbmV0d29yayBkaWFncmFtDQoNCkluIG9yZGVyIHRvIGRvIHRoaXMgSSBiYXNpY2FsbHkgd2FudCB0byBkZXBpY3QgdGhlIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiBwZW9wbGUNCmFuZCBob3cgaW1wb3J0YW50IHBlb3BsZSBhcmUgdG8gdGhlIGNvbnZlcnNhdGlvbi4NCg0KRmVhdHVyZXMgaW5jbHVkZToNCg0KKiBub2RlcyB0aGF0IGFyZSBzaXplZCBiYXNlZCBvbiBudW1iZXIgb2YgbWVzc2FnZXMgYSBwZXJzb24gc2VudCAqIGRpcmVjdGlvbmFsDQpmbG93cyB0aGF0IGFyZSByZWxhdGVkIHRvIG51bWJlciBvZiBtZXNzYWdlcyBzZW50ICogZG8gdGhpcyBmb3IgaW5kaXZpZHVhbCB3b3Jkcw0KDQoNCmBgYHtyfQ0KDQpsaWJyYXJ5KHZpc05ldHdvcmspIA0KbGlicmFyeShpZ3JhcGgpDQoNCg0KIyBDcmVhdGUgbm9kZXMgZGF0YS5mcmFtZQ0KDQpsaWJyYXJ5KGRwbHlyKSANCmxpYnJhcnkobWFncml0dHIpDQoNCiMgY3JlYXRlIG5hbWVzDQpub2RlcyA8LSBkYXRhLmZyYW1lKHNlbGVjdCh0bXAsIHNlbmRlcikgJT4lIGRpc3RpbmN0KCkpIA0KbmFtZXMobm9kZXMpIDwtICJpZCINCg0KDQojIGNyZWF0ZSBudW1iZXIgb2YgbWVzc2FnZXMgc2VudCANCnRvdGFscyA8LSBzZWxlY3QodG1wLCBzZW5kZXIpICU+JQ0KICBncm91cF9ieShzZW5kZXIpICU+JSANCiAgc3VtbWFyaXNlKHN1bSA9IG4oKSkgDQoNCm5vZGVzJHNpemUgPC0gKHRvdGFscyRzdW0gKjEwMCkvc3VtKHRvdGFscyRzdW0pDQojIENyZWF0ZSBlZGdlcyBvZiBkYXRhLmZyYW1lIA0KDQpyZXNwb25zZXMgPC0gcmVzcG9uc2VfbWF0cml4KHRtcCwgMSkgDQoNCnJlc3BvbnNlcyA8LWFzLmRhdGEuZnJhbWUocmVzcG9uc2VzKQ0KcmVzcG9uc2VzJG5hbWUgPC0gcm93Lm5hbWVzKHJlc3BvbnNlcykgDQpyZXNwb25zZXNfbSA8LSBtZWx0KHJlc3BvbnNlcykgDQpuYW1lcyhyZXNwb25zZXNfbSkgPC0gYygiZnJvbSIsInRvIiwgIm51bWJlciIpDQoNCiMgZm9ybWF0IGFzIG5ldHdvcmsNCg0KZWRnZXMgPC0gcmVzcG9uc2VzX20gDQplZGdlcyR0byA8LSBhcy5jaGFyYWN0ZXIoZWRnZXMkdG8pIA0KZWRnZXMkd2lkdGggPC0gKGVkZ2VzJG51bWJlciAqIDEwMCkvc3VtKHRvdGFscyRzdW0pDQplZGdlcyR0aXRsZSA8LSBwYXN0ZSgiPHAgc3R5bGU9XCJjb2xvcjpibGFja1wiPiIsZWRnZXMkbnVtYmVyLCI8L3A+IikNCg0KIyBhZGQgaW4gbm9kZSBjb2xvcnMsIG5hbWVzIA0Kbm9kZXMkZ3JvdXAgPC0gbm9kZXMkaWQgDQpub2RlcyRsYWJlbCA8LSBub2RlcyRpZCANCm5vZGVzJHRpdGxlIDwtIHBhc3RlKCI8cCBzdHlsZT1cImNvbG9yOiBibGFja1wiPiIsdG90YWxzJHN1bSwiPC9wPiIpDQoNCiMgcGxvdCBsaWJyYXJ5KHZpc05ldHdvcmspIA0KdmlzTmV0d29yayhub2RlcywgZWRnZXMsIHdpZHRoID0gIjEwMCUiKSAlPiUNCnZpc1BoeXNpY3MoIHNvbHZlciA9J2ZvcmNlQXRsYXMyQmFzZWQnKQ0KDQoNCg0KDQpgYGANCg0KDQoNCg0KDQoNCg0KDQoNCg0KIyBOZXcgYWRkaXRpb25zOg0KDQoqIGRvIGFuYWx5c2lzIG9mIG1lc3NhZ2VzIGJ5IG51bWJlciBvZiB3b3JkcyAoZG9uZSkNCiogZG8gbmV0d29yayBhbmQgdGFibGUgZm9yIGFuIGluZGl2aWR1YWwgd29yZCAodGFibGUgZG9uZSkNCiogdG9waWMgYW5hbHlzaXMgDQoqIGJ1aWxkIGFwcCB0aGF0IGFsbG93cyB5b3UgdG8gdXBsb2FkIGZpbGUgdG8gYW5hbHlzZSAocHJvZHVjZXMgbmV0d29yayBhbmQgd29yZCBjbG91ZHMpDQoNCg0KIyBDb3VudCBudW1iZXIgb2Ygd29yZHMNCg0KYGBge3J9DQoNCiMgQ3JlYXRlIHZhcmlhYmxlIHRoYXQgaXMgbnVtYmVyIG9mIHdvcmRzIHBlciBtZXNzYWdlDQoNCnRlc3QgPC0gInRoaXMgbWVzc2FnZSBoYXMgbWFueSB3b3JkcyBpbiBpdCINCmxlbmd0aCh1bmxpc3Qoc3Ryc3BsaXQodGVzdCwgc3BsaXQgPSAiICIpKSkNCg0KdGVzdDIgPC0gZGF0YS5mcmFtZShjID0gYygibWVzc2FnZSB3aXRoIHRocmVlIiwgIm1lc3NhZ2Ugd2l0aCB0d28iKSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0Kc3RyKHRlc3QyKQ0KbGVuZ3RoKHVubGlzdChzdHJzcGxpdCh0ZXN0MiRjLCBzcGxpdCA9ICIgIikpKQ0KDQoNCmxpYnJhcnkoc3RyaW5ncikNCg0KIyBjcmVhdGUgdmFyaWFibGUgd2l0aCBudW1iZXIgb2Ygd29yZHMgaW4gZWFjaCBsaW5lDQoNCnRtcCAlPD4lIHVuZ3JvdXANCnRtcCAlPiUgbXV0YXRlKG51bWJlcl93b3JkcyA9IHN0cl9jb3VudChtZXNzYWdlLCAiICIpKSAlPiUgZ3JvdXBfYnkoc2VuZGVyKSAlPiUgc3VtbWFyaXNlKHRvdGFsX3dvcmRzID0gc3VtKG51bWJlcl93b3JkcyksIGF2Z19tZXNzYWdlX2xlbmd0aCA9IHRvdGFsX3dvcmRzL21lYW4odG90YWxfbWVzc2FnZXMpKQ0KDQoNCg0KYGBgDQoNCg0KIyBXb3JkIHNlcGVjaWZpYyBtYXRyaXgNCg0KDQpgYGB7cn0NCg0KbGlicmFyeSh2aXNOZXR3b3JrKSANCmxpYnJhcnkoaWdyYXBoKQ0KDQoNCiMgQ3JlYXRlIG5vZGVzIGRhdGEuZnJhbWUNCg0KbGlicmFyeShkcGx5cikgDQpsaWJyYXJ5KG1hZ3JpdHRyKQ0KDQojIGNyZWF0ZSBuYW1lcw0Kbm9kZXMgPC0gZGF0YS5mcmFtZShzZWxlY3QodG1wLCBzZW5kZXIpICU+JSBkaXN0aW5jdCgpKSANCm5hbWVzKG5vZGVzKSA8LSAiaWQiDQoNCg0KIyBjcmVhdGUgbnVtYmVyIG9mIG1lc3NhZ2VzIHNlbnQgDQp0b3RhbHMgPC0gc2VsZWN0KHRtcCwgc2VuZGVyLCBtZXNzYWdlKSAlPiUgDQogIGdyb3VwX2J5KHNlbmRlcikgJT4lIA0KICBzdW1tYXJpc2Uoc3VtID0gbigpKSANCg0Kbm9kZXMkc2l6ZSA8LSAodG90YWxzJHN1bSAqMTAwKS9zdW0odG90YWxzJHN1bSkNCiMgQ3JlYXRlIGVkZ2VzIG9mIGRhdGEuZnJhbWUgDQoNCnJlc3BvbnNlcyA8LSByZXNwb25zZV9tYXRyaXhfd29yZCh0bXAsIDEsIHdvcmQgPSAic2V4IikgDQoNCnJlc3BvbnNlcyA8LWFzLmRhdGEuZnJhbWUocmVzcG9uc2VzKQ0KcmVzcG9uc2VzX3QgPC0gdChyZXNwb25zZXMpICNzbyB0aGF0IG1lbHQgY29ycmVjdGx5IHBpY2tzIHVwIHRvIGFuZCBmcm9tDQpyZXNwb25zZXNfbSA8LSBtZWx0KHJlc3BvbnNlc190KSANCm5hbWVzKHJlc3BvbnNlc19tKSA8LSBjKCJmcm9tIiwidG8iLCAibnVtYmVyIikNCg0KIyBmb3JtYXQgYXMgbmV0d29yaw0KDQplZGdlcyA8LSByZXNwb25zZXNfbSANCmVkZ2VzJHRvIDwtIGFzLmNoYXJhY3RlcihlZGdlcyR0bykgDQplZGdlcyR3aWR0aCA8LSAoZWRnZXMkbnVtYmVyICogNTApL3N1bShlZGdlcyRudW1iZXIpDQplZGdlcyR0aXRsZSA8LSBwYXN0ZSgiPHAgc3R5bGU9XCJjb2xvcjpibGFja1wiPiIsZWRnZXMkbnVtYmVyLCI8L3A+IikNCmVkZ2VzIDwtIGVkZ2VzW2VkZ2VzJG51bWJlciA+IDAsXQ0KDQojIGFkZCBpbiBub2RlIGNvbG9ycywgbmFtZXMgDQpub2RlcyRncm91cCA8LSBub2RlcyRpZCANCm5vZGVzJGxhYmVsIDwtIG5vZGVzJGlkIA0Kbm9kZXMkdGl0bGUgPC0gcGFzdGUoIjxwIHN0eWxlPVwiY29sb3I6IGJsYWNrXCI+Iix0b3RhbHMkc3VtLCI8L3A+IikNCg0KIyBwbG90IGxpYnJhcnkodmlzTmV0d29yaykgDQp2aXNOZXR3b3JrKG5vZGVzLCBlZGdlcywgd2lkdGggPSAiMTAwJSIpICU+JQ0KdmlzUGh5c2ljcyggc29sdmVyID0nZm9yY2VBdGxhczJCYXNlZCcpDQoNCg0KDQoNCmBgYA0KDQoNCg0KDQojIENyZWF0ZSBzaGlueSBhcHAgDQoNClRoZSBmaXJzdCBzdGFnZSBvZiBjcmVhdGluZyB0aGlzIHNoaW55IGFwcCBpcyBqdXN0IG1ha2luZyBpdCBzbyB0aGF0IHRoZSB1c2VyIGNhbiBzZWxlY3QgKHZpYSBhbiBpbnB1dCBib3gpIHdoYXQgd29yZCB0aGUgd291bGQgbGlrZSB0byBsb29rIGF0IHRoZSBuZXR3b3JrIG9mLiANCg0KSWRlYWxseSBJIHdvdWxkIHRoZW4gYWxzbyBtYWtlIGl0IHNvIHRoZSBjYW4ganVzdCBsb29rIGF0IHRoZSBtYXRyaXggb2YgYWxsIG1lc3NhZ2VzIHNlbnQgKG9yIHBlcmhhcHMgaGF2ZSB0aGlzIGFzIGEgc2VwZXJhdGUgcGFydCBvZiB0aGUgYXBwIGZvciBjb21wYXJpc29uIHB1cnBvc2VzKS4NCg0KTGF0ZXIgc3RhZ2VzIG9mIHRoZSBhcHAgc2hvdWxkIHRoZW4gYWRkIHNvbWUgYWRkaXRpb25hbCBzdW1tYXJ5IG1lYXN1cmVzIChwZXJzb24gc3BlY2lmaWMgd29yZCBjbG91ZCwgbWVzc2FnZXMgc2VudCBvdmVyIHRpbWUsIG1lc3NhZ2VzIHNlbnQgb3ZlciB0aW1lIGNvbnRhaW5pbmcgYSBwYXJ0aWN1bGFyIHdvcmQsIGV0YykuIA0KDQoNCmBgYHtyfQ0KDQojIyBTZXR1cA0KDQojIGNyZWF0ZSBuYW1lcw0Kbm9kZXMgPC0gZGF0YS5mcmFtZShzZWxlY3QodG1wLCBzZW5kZXIpICU+JSBkaXN0aW5jdCgpKSANCm5hbWVzKG5vZGVzKSA8LSAiaWQiDQoNCiMgYWRkIGluIG5vZGUgY29sb3JzLCBuYW1lcyANCm5vZGVzJGdyb3VwIDwtIG5vZGVzJGlkIA0Kbm9kZXMkbGFiZWwgPC0gbm9kZXMkaWQgDQpub2RlcyR0aXRsZSA8LSBwYXN0ZSgiPHAgc3R5bGU9XCJjb2xvcjogYmxhY2tcIj4iLHRvdGFscyRzdW0sIjwvcD4iKQ0KDQoNCg0KDQpyZXF1aXJlKHNoaW55KQ0KcmVxdWlyZSh2aXNOZXR3b3JrKQ0KDQpzZXJ2ZXIgPC0gZnVuY3Rpb24oaW5wdXQsIG91dHB1dCkgew0KICBvdXRwdXQkbmV0d29yayA8LSByZW5kZXJWaXNOZXR3b3JrKHsNCiANCiAgICAjIGNyZWF0ZSBudW1iZXIgb2YgbWVzc2FnZXMgc2VudCBmb3Igbm9kZSBzaXplDQogICAgd29yZCA8LSAic2V4Ig0KICAgIA0KICAgIHRvdGFscyA8LSBzZWxlY3QodG1wLCBzZW5kZXIsIG1lc3NhZ2UpICU+JQ0KICAgICAgbXV0YXRlKGluZCA9IGlmZWxzZShncmVwbChpbnB1dCR3b3JkLCB0bXAkbWVzc2FnZSksIDEsIDApKSAlPiUgDQogICAgICBncm91cF9ieShzZW5kZXIpICU+JSANCiAgICAgIHN1bW1hcmlzZShzdW0gPSBzdW0oaW5kKSkgDQogICAgDQogICAgbm9kZXMkc2l6ZSA8LSBwbWF4KCh0b3RhbHMkc3VtICoxMDApL3N1bSh0b3RhbHMkc3VtKSwgNzUvc3VtKHRvdGFscyRzdW0pKQ0KICAgIA0KICAgICMgY3JlYXRlIHJlc3BvbnNlIG1hdHJpeA0KICAgIHJlc3BvbnNlcyA8LSByZXNwb25zZV9tYXRyaXhfd29yZCh0bXAsIDEsIHdvcmQgPSBpbnB1dCR3b3JkKSANCiAgICByZXNwb25zZXMgPC1hcy5kYXRhLmZyYW1lKHJlc3BvbnNlcykNCiAgICByZXNwb25zZXNfdCA8LSB0KHJlc3BvbnNlcykgI3NvIHRoYXQgbWVsdCBjb3JyZWN0bHkgcGlja3MgdXAgdG8gYW5kIGZyb20NCiAgICByZXNwb25zZXNfbSA8LSBtZWx0KHJlc3BvbnNlc190KSANCiAgICBuYW1lcyhyZXNwb25zZXNfbSkgPC0gYygiZnJvbSIsInRvIiwgIm51bWJlciIpDQogICAgDQogICAgIyBmb3JtYXQgYXMgbmV0d29yayBlZGdlcw0KICAgIGVkZ2VzIDwtIHJlc3BvbnNlc19tIA0KICAgIGVkZ2VzJHRvIDwtIGFzLmNoYXJhY3RlcihlZGdlcyR0bykgDQogICAgZWRnZXMkd2lkdGggPC0gKGVkZ2VzJG51bWJlciAqIDUwKS9zdW0oZWRnZXMkbnVtYmVyKQ0KICAgIGVkZ2VzJHRpdGxlIDwtIHBhc3RlKCI8cCBzdHlsZT1cImNvbG9yOmJsYWNrXCI+IixlZGdlcyRudW1iZXIsIjwvcD4iKQ0KICAgIGVkZ2VzIDwtIGVkZ2VzW2VkZ2VzJG51bWJlciA+IDAsXQ0KDQogICAgDQoNCiAgICAjIHJlbmRlciBuZXR3b3JrIA0KICAgIHZpc05ldHdvcmsobm9kZXMsIGVkZ2VzKSAlPiUNCiAgICAgIHZpc1BoeXNpY3MoIHNvbHZlciA9J2ZvcmNlQXRsYXMyQmFzZWQnKQ0KICB9KQ0KfQ0KDQp1aSA8LSBmbHVpZFBhZ2UoDQogIA0KICAgICMgY3JlYXRlIHVzZXIgaW5wdXQgd29yZCBib3ggDQogICAgdGV4dElucHV0KCJ3b3JkIiwgIldvcmQiLCB2YWx1ZSA9ICJoaSIpLA0KDQogICAgIyByZW5kZXIgb3V0cHV0DQogICAgdmlzTmV0d29ya091dHB1dCgibmV0d29yayIpDQopDQoNCnNoaW55QXBwKHVpID0gdWksIHNlcnZlciA9IHNlcnZlcikNCg0KDQoNCmBgYA0KDQoNCiMgQ3JlYXRlIGFuIGFwcCB0aGF0IHRha2VzIGEgd2hhdHNhcHAgZmlsZSBhcyBpbnB1dCANCg0KVGhpcyBpcyB0aGUgZmlyc3Qgc3RhZ2Ugb2YgY3JlYXRpbmcgdGhlIGVuZCB1c2VyIHNoaW55IGFwcGxpY2F0aW9uLiBJdCBuZWVkcyB0byBiZSBhYmxlIHRvIGxvYWQgYW55IHdoYXRzYXBwIGZpbGUgYW5kIHByb2R1Y2UgYmFzaWMgYW5hbHlzaXMgbGlrZSB0aGUgbmV0d29yayBhYm92ZS4gDQoNCkluIHRoZSBmaXJzdCBpbnN0YW5jZSBJJ20ganVzdCBnb2luZyB0byBnZXQgaXQgdG8gbG9hZCBhIGZpbGUsIGZvcm1hdCBhcyBhIGRhdGEuZnJhbWUsIGFuZCB0aGVuIHByaW50IHRoZSBmaXJzdCAxMCByb3dzIG9mIHRoYXQgZGF0YS5mcmFtZS4gDQoNCg0KDQojIGN1cnJlbnRseSBidWlsdCBzaGlueSBhcHANCg0KTm90ZXM6IEkgYW0gY29uY2VybmVkIHRoYXQgdGhpcyBhY3R1YWxseSBkZXBlbmRzIG9uIHRoZSB2YWx1ZSBvZiB0bXAgaW4gdGhlIG90aGVyIGRhdGEgKHJhdGhlciB0aGFuIHdoYXQgaXMgbG9hZGVkKS4NCg0KR29pbmcgdG8gdGVzdCB0aGlzIGJ5IGNoYW5naW5nIHRvIHRtcDEuIEFsbCBzdGlsbCBzZWVtcyB0byB3b3JrDQoNCmBgYHtyfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHNoaW55KQ0KbGlicmFyeSh2aXNOZXR3b3JrKQ0KDQoNCg0KDQp1aSA8LSBmbHVpZFBhZ2UoDQogIHNpZGViYXJMYXlvdXQoDQogICAgc2lkZWJhclBhbmVsKA0KICAgICAgZmlsZUlucHV0KCJmaWxlMSIsICJDaG9vc2UgQ1NWIEZpbGUiLA0KICAgICAgICBhY2NlcHQgPSBjKA0KICAgICAgICAgICJ0ZXh0L2NzdiIsDQogICAgICAgICAgInRleHQvY29tbWEtc2VwYXJhdGVkLXZhbHVlcyx0ZXh0L3BsYWluIiwNCiAgICAgICAgICAiLmNzdiIpDQogICAgICAgICksDQogICAgICB0YWdzJGhyKCksDQogICAgICBjaGVja2JveElucHV0KCJoZWFkZXIiLCAiSGVhZGVyIiwgVFJVRSksICAgIA0KICAgICAgDQogICAgICAjIGNyZWF0ZSB1c2VyIGlucHV0IHdvcmQgYm94IA0KICAgICAgdGV4dElucHV0KCJ3b3JkIiwgIldvcmQiLCB2YWx1ZSA9ICJoaSIpDQoNCiAgIA0KICAgICksDQogICAgbWFpblBhbmVsKA0KICAgICAgIA0KICAgICAgIyByZW5kZXIgb3V0cHV0DQogICAgICB2aXNOZXR3b3JrT3V0cHV0KCJuZXR3b3JrIikNCiAgICAgIA0KICAgICAgDQogICAgKQ0KICApDQopDQoNCg0Kc2VydmVyIDwtIGZ1bmN0aW9uKGlucHV0LCBvdXRwdXQpIHsNCg0KICAgICMgQ3JlYXRlIE5ldHdvcmsgIA0KICAgIG91dHB1dCRuZXR3b3JrIDwtIHJlbmRlclZpc05ldHdvcmsoew0KICAgIA0KICAgIA0KICAgICMgaW5wdXQkZmlsZTEgd2lsbCBiZSBOVUxMIGluaXRpYWxseS4gQWZ0ZXIgdGhlIHVzZXIgc2VsZWN0cw0KICAgICMgYW5kIHVwbG9hZHMgYSBmaWxlLCBpdCB3aWxsIGJlIGEgZGF0YSBmcmFtZQ0KICAgIGluRmlsZSA8LSBpbnB1dCRmaWxlMQ0KDQogICAgaWYgKGlzLm51bGwoaW5GaWxlKSkNCiAgICAgIHJldHVybihOVUxMKQ0KDQogICAgbG9hZGVkX2NoYXQgPC0gcmVhZC50YWJsZShpbkZpbGUkZGF0YXBhdGgsICANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD1UUlVFLCBoZWFkZXI9aW5wdXQkaGVhZGVyLCBxdW90ZT0iIiwgc2VwPSJcbiIsIGVuY29kaW5nPSJVVEYtOCIpDQogICAgbmFtZXMobG9hZGVkX2NoYXQpIDwtICJzdHJpbmciDQogICAgIA0KICAgICMgZm9ybWF0IHRoZSBkYXRhIGFuZCBzcGxpdCBpbnRvIGRpZmZlcmVudCBjb2x1bW5zDQogICAgcmVneCA8LSAiKFxcZCsvXFxkKy9cXGQrKSxcXHMrKFxcZCs6XFxkKzpcXGQrIFtBfFBdTSk6XFxzKyhcXHcrXFxzKlxcdyspOlxccysoLiopIg0KICAgIHRtcCA8LSBsb2FkZWRfY2hhdCAlPiUNCiAgICAgICAgIHRpZHlyOjpleHRyYWN0KHN0cmluZywgYygiZGF0ZSIsICJ0aW1lIiwgInNlbmRlciIsICJtZXNzYWdlIiksIHJlZ3gsIHJlbW92ZT1GQUxTRSkNCiAgICAgDQogICAgIHRtcCA8LSBmaWx0ZXIodG1wLCAhaXMubmEoc2VuZGVyKSkNCiAgICAgDQogICAgIyBjcmVhdGUgbm9kZXMgbGlzdA0KICAgIG5vZGVzIDwtIGRhdGEuZnJhbWUoc2VsZWN0KHRtcCwgc2VuZGVyKSAlPiUgZGlzdGluY3QoKSkgDQogICAgbmFtZXMobm9kZXMpIDwtICJpZCINCg0KICAgICMgYWRkIGluIG5vZGUgY29sb3JzLCBuYW1lcyANCiAgICBub2RlcyRncm91cCA8LSBub2RlcyRpZCANCiAgICBub2RlcyRsYWJlbCA8LSBub2RlcyRpZA0KDQogICAgI2NyZWF0ZSBudW1iZXIgb2YgbWVzc2FnZXMgc2VudCBmb3Igbm9kZSBzaXplDQogICAgdG90YWxzIDwtIHNlbGVjdCh0bXAsIHNlbmRlciwgbWVzc2FnZSkgJT4lDQogICAgICBtdXRhdGUoaW5kID0gaWZlbHNlKGdyZXBsKGlucHV0JHdvcmQsIG1lc3NhZ2UpLCAxLCAwKSkgJT4lDQogICAgICBncm91cF9ieShzZW5kZXIpICU+JQ0KICAgICAgc3VtbWFyaXNlKHRvdGFsX21lc3NhZ2VzID0gc3VtKGluZCkpDQoNCiAgDQogICAgbm9kZXMgPC0gbGVmdF9qb2luKG5vZGVzLCB0b3RhbHMsIGJ5PWMoImlkIj0ic2VuZGVyIikpDQogICAgbm9kZXMkc2l6ZSA8LSBwbWF4KChub2RlcyR0b3RhbF9tZXNzYWdlcyAqMTAwKS9zdW0obm9kZXMkdG90YWxfbWVzc2FnZXMpLCA3NS9zdW0obm9kZXMkdG90YWxfbWVzc2FnZXMpKQ0KICAgIG5vZGVzJHRpdGxlIDwtIHBhc3RlKCI8cCBzdHlsZT1cImNvbG9yOiBibGFja1wiPiIsbm9kZXMkdG90YWxfbWVzc2FnZXMsIjwvcD4iKQ0KICAgIA0KDQogICAgIyBjcmVhdGUgcmVzcG9uc2UgbWF0cml4DQogICAgcmVzcG9uc2VzIDwtIHJlc3BvbnNlX21hdHJpeF93b3JkKHRtcCwgMSwgd29yZCA9IGlucHV0JHdvcmQpDQogICAgcmVzcG9uc2VzIDwtYXMuZGF0YS5mcmFtZShyZXNwb25zZXMpDQogICAgcmVzcG9uc2VzX3QgPC0gdChyZXNwb25zZXMpICNzbyB0aGF0IG1lbHQgY29ycmVjdGx5IHBpY2tzIHVwIHRvIGFuZCBmcm9tDQogICAgcmVzcG9uc2VzX20gPC0gbWVsdChyZXNwb25zZXNfdCkNCiAgICBuYW1lcyhyZXNwb25zZXNfbSkgPC0gYygiZnJvbSIsInRvIiwgIm51bWJlciIpDQogICAgDQogICAgDQogICAgIyBmb3JtYXQgYXMgbmV0d29yayBlZGdlcw0KICAgIGVkZ2VzIDwtIHJlc3BvbnNlc19tIA0KICAgIGVkZ2VzJHRvIDwtIGFzLmNoYXJhY3RlcihlZGdlcyR0bykgDQogICAgZWRnZXMkd2lkdGggPC0gKGVkZ2VzJG51bWJlciAqIDUwKS9zdW0oZWRnZXMkbnVtYmVyKQ0KICAgIGVkZ2VzJHRpdGxlIDwtIHBhc3RlKCI8cCBzdHlsZT1cImNvbG9yOmJsYWNrXCI+IixlZGdlcyRudW1iZXIsIjwvcD4iKQ0KICAgIGVkZ2VzIDwtIGVkZ2VzW2VkZ2VzJG51bWJlciA+IDAsXQ0KDQogICAgIyByZW5kZXIgbmV0d29yayANCiAgICB2aXNOZXR3b3JrKG5vZGVzLCBlZGdlcykgJT4lDQogICAgICB2aXNQaHlzaWNzKCBzb2x2ZXIgPSdmb3JjZUF0bGFzMkJhc2VkJykNCiAgfSkNCiAgDQogIA0KfQ0KDQpzaGlueUFwcCh1aSwgc2VydmVyKQ0KDQoNCg0KYGBgDQoNCg0KIyBnZXQgaXQgd29ya2luZyBwcmUgc2hpbnkgYXBwDQoNCmBgYHtyfQ0KbGlicmFyeShkYXRhLnRhYmxlKQ0KbGlicmFyeSh0aWR5cikNCiAgICANCiAgICAjY2hhdCA8LSBmcmVhZCgiQzovVXNlcnMvcm9iZXIvRGVza3RvcC90ZXh0LmNzdiIsIGJsYW5rLmxpbmVzLnNraXAgPSBUUlVFKQ0KICAgIHRtcDEgPC0gcmVhZC50YWJsZSgiQzovVXNlcnMvcm9iZXIvRGVza3RvcC9jaGF0Mi50eHQiLCAgZmlsbD1UUlVFLCBoZWFkZXI9VFJVRSwgcXVvdGU9IiIsIHNlcD0iXG4iLCBlbmNvZGluZz0iVVRGLTgiKQ0KICAgIG5hbWVzKHRtcDEpIDwtICJzdHJpbmciDQoNCiAgICAjIGZvcm1hdCB0aGUgZGF0YSBhbmQgc3BsaXQgaW50byBkaWZmZXJlbnQgY29sdW1ucw0KICAgIHJlZ3ggPC0gIihcXGQrL1xcZCsvXFxkKyksXFxzKyhcXGQrOlxcZCs6XFxkKyBbQXxQXU0pOlxccysoXFx3K1xccypcXHcrKTpcXHMrKC4qKSINCiAgICB0bXAxIDwtIHRtcDEgJT4lDQogICAgICAgIHRpZHlyOjpleHRyYWN0KHN0cmluZywgYygiZGF0ZSIsICJ0aW1lIiwgInNlbmRlciIsICJtZXNzYWdlIiksIHJlZ3gsIHJlbW92ZT1GQUxTRSkNCg0KDQogICAgDQogICAgdG1wMSA8LSBmaWx0ZXIodG1wMSwgIWlzLm5hKHNlbmRlcikpDQogICAgDQogICAgIyBjcmVhdGUgbm9kZXMgbGlzdA0KICAgIG5vZGVzIDwtIGRhdGEuZnJhbWUoc2VsZWN0KHRtcDEsIHNlbmRlcikgJT4lIGRpc3RpbmN0KCkpIA0KICAgIG5hbWVzKG5vZGVzKSA8LSAiaWQiDQoNCiAgICAjIGFkZCBpbiBub2RlIGNvbG9ycywgbmFtZXMgDQogICAgbm9kZXMkZ3JvdXAgPC0gbm9kZXMkaWQgDQogICAgbm9kZXMkbGFiZWwgPC0gbm9kZXMkaWQNCiAgICANCiAgICAjIGNyZWF0ZSBudW1iZXIgb2YgbWVzc2FnZXMgc2VudCBmb3Igbm9kZSBzaXplDQogICAgd29yZCA9ICJoaSINCiAgICANCiAgICB0b3RhbHMgPC0gc2VsZWN0KHRtcDEsIHNlbmRlciwgbWVzc2FnZSkgJT4lDQogICAgICBtdXRhdGUoaW5kID0gaWZlbHNlKGdyZXBsKHdvcmQsIHRtcDEkbWVzc2FnZSksIDEsIDApKSAlPiUgDQogICAgICBncm91cF9ieShzZW5kZXIpICU+JSANCiAgICAgIHN1bW1hcmlzZShzdW0gPSBzdW0oaW5kKSkgDQogICAgDQogICAgbm9kZXMgPC0gbGVmdF9qb2luKG5vZGVzLCB0b3RhbHMsIGJ5PWMoImlkIj0ic2VuZGVyIikpDQogICAgbm9kZXMkc2l6ZSA8LSBwbWF4KChub2RlcyRzdW0gKjEwMCkvc3VtKG5vZGVzJHN1bSksIDc1L3N1bShub2RlcyRzdW0pKQ0KICAgIG5vZGVzJHRpdGxlIDwtIHBhc3RlKCI8cCBzdHlsZT1cImNvbG9yOiBibGFja1wiPiIsbm9kZXMkc3VtLCI8L3A+IikNCiAgICANCiAgICAjIGNyZWF0ZSByZXNwb25zZSBtYXRyaXgNCiAgICByZXNwb25zZXMgPC0gcmVzcG9uc2VfbWF0cml4X3dvcmQodG1wMSwgMSwgd29yZCA9IHdvcmQpIA0KICAgIHJlc3BvbnNlcyA8LWFzLmRhdGEuZnJhbWUocmVzcG9uc2VzKQ0KICAgIHJlc3BvbnNlc190IDwtIHQocmVzcG9uc2VzKSAjc28gdGhhdCBtZWx0IGNvcnJlY3RseSBwaWNrcyB1cCB0byBhbmQgZnJvbQ0KICAgIHJlc3BvbnNlc19tIDwtIG1lbHQocmVzcG9uc2VzX3QpIA0KICAgIG5hbWVzKHJlc3BvbnNlc19tKSA8LSBjKCJmcm9tIiwidG8iLCAibnVtYmVyIikNCiAgICANCiAgICAjIGZvcm1hdCBhcyBuZXR3b3JrIGVkZ2VzDQogICAgZWRnZXMgPC0gcmVzcG9uc2VzX20gDQogICAgZWRnZXMkdG8gPC0gYXMuY2hhcmFjdGVyKGVkZ2VzJHRvKSANCiAgICBlZGdlcyR3aWR0aCA8LSAoZWRnZXMkbnVtYmVyICogNTApL3N1bShlZGdlcyRudW1iZXIpDQogICAgZWRnZXMkdGl0bGUgPC0gcGFzdGUoIjxwIHN0eWxlPVwiY29sb3I6YmxhY2tcIj4iLGVkZ2VzJG51bWJlciwiPC9wPiIpDQogICAgZWRnZXMgPC0gZWRnZXNbZWRnZXMkbnVtYmVyID4gMCxdDQoNCiAgICAjIHJlbmRlciBuZXR3b3JrIA0KICAgIHZpc05ldHdvcmsobm9kZXMsIGVkZ2VzKSAlPiUNCiAgICB2aXNQaHlzaWNzKCBzb2x2ZXIgPSdmb3JjZUF0bGFzMkJhc2VkJykNCiAgICANCnRvdGFscw0KZWRnZXMgJT4lIGdyb3VwX2J5KGZyb20pICU+JSBzdW1tYXJpc2Uobj1zdW0obnVtYmVyKSkNCnJlc3BvbnNlc19tICAgDQoNCmBgYA0KDQoNCg0KIyBUYWJsZSB2ZXJzaW9uIChyYXRoZXIgdGhhbiBuZXR3b3JrKSANCg0KVXNlZnVsIGZvciB0ZXN0aW5nIG91dCBjb2RlDQoNCmBgYHtyfQ0KIyMgT25seSBydW4gZXhhbXBsZXMgaW4gaW50ZXJhY3RpdmUgUiBzZXNzaW9ucw0KaWYgKGludGVyYWN0aXZlKCkpIHsNCg0KdWkgPC0gZmx1aWRQYWdlKA0KICBzaWRlYmFyTGF5b3V0KA0KICAgIHNpZGViYXJQYW5lbCgNCiAgICAgIGZpbGVJbnB1dCgiZmlsZTEiLCAiQ2hvb3NlIENTViBGaWxlIiwNCiAgICAgICAgYWNjZXB0ID0gYygNCiAgICAgICAgICAidGV4dC9jc3YiLA0KICAgICAgICAgICJ0ZXh0L2NvbW1hLXNlcGFyYXRlZC12YWx1ZXMsdGV4dC9wbGFpbiIsDQogICAgICAgICAgIi5jc3YiLA0KICAgICAgICAgICIudHh0IikNCiAgICAgICAgKSwNCiAgICAgIHRhZ3MkaHIoKSwNCiAgICAgIGNoZWNrYm94SW5wdXQoImhlYWRlciIsICJIZWFkZXIiLCBUUlVFKSwNCiAgICAgIA0KICAgICAgIyBjcmVhdGUgdXNlciBpbnB1dCB3b3JkIGJveCANCiAgICAgIHRleHRJbnB1dCgid29yZCIsICJXb3JkIiwgdmFsdWUgPSAiaGkiKQ0KICAgICAgDQogICAgKSwNCiAgICBtYWluUGFuZWwoDQogICAgICB0YWJsZU91dHB1dCgiY29udGVudHMiKQ0KICAgICkNCiAgKQ0KKQ0KDQpzZXJ2ZXIgPC0gZnVuY3Rpb24oaW5wdXQsIG91dHB1dCkgew0KICBvdXRwdXQkY29udGVudHMgPC0gcmVuZGVyVGFibGUoew0KICAgICMgaW5wdXQkZmlsZTEgd2lsbCBiZSBOVUxMIGluaXRpYWxseS4gQWZ0ZXIgdGhlIHVzZXIgc2VsZWN0cw0KICAgICMgYW5kIHVwbG9hZHMgYSBmaWxlLCBpdCB3aWxsIGJlIGEgZGF0YSBmcmFtZSB3aXRoICduYW1lJywNCiAgICAjICdzaXplJywgJ3R5cGUnLCBhbmQgJ2RhdGFwYXRoJyBjb2x1bW5zLiBUaGUgJ2RhdGFwYXRoJw0KICAgICMgY29sdW1uIHdpbGwgY29udGFpbiB0aGUgbG9jYWwgZmlsZW5hbWVzIHdoZXJlIHRoZSBkYXRhIGNhbg0KICAgICMgYmUgZm91bmQuDQogICAgaW5GaWxlIDwtIGlucHV0JGZpbGUxDQoNCiAgICBpZiAoaXMubnVsbChpbkZpbGUpKQ0KICAgICAgcmV0dXJuKE5VTEwpDQoNCiAgICAgIGxvYWRlZF9jaGF0IDwtIHJlYWQudGFibGUoaW5GaWxlJGRhdGFwYXRoLCAgZmlsbD1UUlVFLCBoZWFkZXI9aW5wdXQkaGVhZGVyLCBxdW90ZT0iIiwgc2VwPSJcbiIsIGVuY29kaW5nPSJVVEYtOCIpDQogICAgICBuYW1lcyhsb2FkZWRfY2hhdCkgPC0gInN0cmluZyINCiAgICAgIGxvYWRlZF9jaGF0DQogICAgIA0KICAgICMgZm9ybWF0IHRoZSBkYXRhIGFuZCBzcGxpdCBpbnRvIGRpZmZlcmVudCBjb2x1bW5zDQogICAgIHJlZ3ggPC0gIihcXGQrL1xcZCsvXFxkKyksXFxzKyhcXGQrOlxcZCs6XFxkKyBbQXxQXU0pOlxccysoXFx3K1xccypcXHcrKTpcXHMrKC4qKSINCiAgICAgdG1wMSA8LSBsb2FkZWRfY2hhdCAlPiUNCiAgICAgICAgIHRpZHlyOjpleHRyYWN0KHN0cmluZywgYygiZGF0ZSIsICJ0aW1lIiwgInNlbmRlciIsICJtZXNzYWdlIiksIHJlZ3gsIHJlbW92ZT1GQUxTRSkNCiAgICAgDQogICAgIHRtcDEgPC0gZmlsdGVyKHRtcDEsICFpcy5uYShzZW5kZXIpKQ0KICAgICANCiAgICAjIGNyZWF0ZSBub2RlcyBsaXN0DQogICAgbm9kZXMgPC0gZGF0YS5mcmFtZShzZWxlY3QodG1wMSwgc2VuZGVyKSAlPiUgZGlzdGluY3QoKSkgDQogICAgbmFtZXMobm9kZXMpIDwtICJpZCINCg0KICAgICMgYWRkIGluIG5vZGUgY29sb3JzLCBuYW1lcyANCiAgICBub2RlcyRncm91cCA8LSBub2RlcyRpZCANCiAgICBub2RlcyRsYWJlbCA8LSBub2RlcyRpZA0KDQogICAgI2NyZWF0ZSBudW1iZXIgb2YgbWVzc2FnZXMgc2VudCBmb3Igbm9kZSBzaXplDQogICAgdG90YWxzIDwtIHNlbGVjdCh0bXAxLCBzZW5kZXIsIG1lc3NhZ2UpICU+JQ0KICAgICAgbXV0YXRlKGluZCA9IGlmZWxzZShncmVwbChpbnB1dCR3b3JkLCBtZXNzYWdlKSwgMSwgMCkpICU+JQ0KICAgICAgZ3JvdXBfYnkoc2VuZGVyKSAlPiUNCiAgICAgIHN1bW1hcmlzZShzdW0gPSBzdW0oaW5kKSkNCg0KICANCiAgICBub2RlcyRzaXplIDwtIHBtYXgoKHRvdGFscyRzdW0gKjEwMCkvc3VtKHRvdGFscyRzdW0pLCA3NS9zdW0odG90YWxzJHN1bSkpDQogICAgbm9kZXMkdGl0bGUgPC0gcGFzdGUoIjxwIHN0eWxlPVwiY29sb3I6IGJsYWNrXCI+Iix0b3RhbHMkc3VtLCI8L3A+IikNCg0KDQogICAgIyBjcmVhdGUgcmVzcG9uc2UgbWF0cml4DQogICAgcmVzcG9uc2VzIDwtIHJlc3BvbnNlX21hdHJpeF93b3JkKHRtcDEsIDEsIHdvcmQgPSBpbnB1dCR3b3JkKQ0KICAgIHJlc3BvbnNlcyA8LWFzLmRhdGEuZnJhbWUocmVzcG9uc2VzKQ0KICAgIHJlc3BvbnNlc190IDwtIHQocmVzcG9uc2VzKSAjc28gdGhhdCBtZWx0IGNvcnJlY3RseSBwaWNrcyB1cCB0byBhbmQgZnJvbQ0KICAgIHJlc3BvbnNlc19tIDwtIG1lbHQocmVzcG9uc2VzX3QpDQogICAgbmFtZXMocmVzcG9uc2VzX20pIDwtIGMoImZyb20iLCJ0byIsICJudW1iZXIiKQ0KDQogICAgcmVzcG9uc2VzX20NCiAgICANCiAgfSkNCn0NCg0Kc2hpbnlBcHAodWksIHNlcnZlcikNCn0NCg0KYGBgDQoNCg0KDQoNCg0KIyBOZXR3b3JrIGNvbXBhcmlzb24gYXBwIA0KDQoNCg0KIyBOZXR3b3JrIGNvbXBhcmlzb24gYXBwIA0KDQoNCiMgV3JpdGUgdGhlIGZ1bmN0aW9uIHRoYXQgcmVuZGVycyB0aGUgbmV0d29yayANCg0KYGBge3J9DQpsaWJyYXJ5KHJlc2hhcGUyKQ0KDQpjcmVhdGVfbmV0d29ya193aGF0c2FwcCA8LSBmdW5jdGlvbihmaWxlLCB3b3JkKXsNCiAgICAjIGxvYWQgY2hhdCAgDQogICAgbG9hZGVkX2NoYXQgPC0gcmVhZC50YWJsZShmaWxlLCAgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbGw9VFJVRSwgaGVhZGVyPVRSVUUsIHF1b3RlPSIiLCBzZXA9IlxuIiwgZW5jb2Rpbmc9IlVURi04IikNCiAgICBuYW1lcyhsb2FkZWRfY2hhdCkgPC0gInN0cmluZyINCiAgICAgDQogICAgIyBmb3JtYXQgdGhlIGRhdGEgYW5kIHNwbGl0IGludG8gZGlmZmVyZW50IGNvbHVtbnMNCiAgICByZWd4IDwtICIoXFxkKy9cXGQrL1xcZCspLFxccysoXFxkKzpcXGQrOlxcZCsgW0F8UF1NKTpcXHMrKFxcdytcXHMqXFx3Kyk6XFxzKyguKikiDQogICAgdG1wIDwtIGxvYWRlZF9jaGF0ICU+JQ0KICAgICAgICAgdGlkeXI6OmV4dHJhY3Qoc3RyaW5nLCBjKCJkYXRlIiwgInRpbWUiLCAic2VuZGVyIiwgIm1lc3NhZ2UiKSwgcmVneCwgcmVtb3ZlPUZBTFNFKQ0KICAgICANCiAgICAgdG1wIDwtIGZpbHRlcih0bXAsICFpcy5uYShzZW5kZXIpKQ0KICAgICANCiAgICAjIGNyZWF0ZSBub2RlcyBsaXN0DQogICAgbm9kZXMgPC0gZGF0YS5mcmFtZShzZWxlY3QodG1wLCBzZW5kZXIpICU+JSBkaXN0aW5jdCgpKSANCiAgICBuYW1lcyhub2RlcykgPC0gImlkIg0KDQogICAgIyBhZGQgaW4gbm9kZSBjb2xvcnMsIG5hbWVzIA0KICAgIG5vZGVzJGdyb3VwIDwtIG5vZGVzJGlkIA0KICAgIG5vZGVzJGxhYmVsIDwtIG5vZGVzJGlkDQoNCiAgICAjY3JlYXRlIG51bWJlciBvZiBtZXNzYWdlcyBzZW50IGZvciBub2RlIHNpemUNCiAgICB0b3RhbHMgPC0gc2VsZWN0KHRtcCwgc2VuZGVyLCBtZXNzYWdlKSAlPiUNCiAgICAgIG11dGF0ZShpbmQgPSBpZmVsc2UoZ3JlcGwod29yZCwgbWVzc2FnZSksIDEsIDApKSAlPiUNCiAgICAgIGdyb3VwX2J5KHNlbmRlcikgJT4lDQogICAgICBzdW1tYXJpc2UodG90YWxfbWVzc2FnZXMgPSBzdW0oaW5kKSkNCg0KICANCiAgICBub2RlcyA8LSBsZWZ0X2pvaW4obm9kZXMsIHRvdGFscywgYnk9YygiaWQiPSJzZW5kZXIiKSkNCiAgICBub2RlcyRzaXplIDwtIHBtYXgoKG5vZGVzJHRvdGFsX21lc3NhZ2VzICoxMDApL3N1bShub2RlcyR0b3RhbF9tZXNzYWdlcyksIDc1L3N1bShub2RlcyR0b3RhbF9tZXNzYWdlcykpDQogICAgbm9kZXMkdGl0bGUgPC0gcGFzdGUoIjxwIHN0eWxlPVwiY29sb3I6IGJsYWNrXCI+Iixub2RlcyR0b3RhbF9tZXNzYWdlcywiPC9wPiIpDQogICAgDQoNCiAgICAjIGNyZWF0ZSByZXNwb25zZSBtYXRyaXgNCiAgICByZXNwb25zZXMgPC0gcmVzcG9uc2VfbWF0cml4X3dvcmQodG1wLCAxLCB3b3JkID0gd29yZCkNCiAgICByZXNwb25zZXMgPC1hcy5kYXRhLmZyYW1lKHJlc3BvbnNlcykNCiAgICByZXNwb25zZXNfdCA8LSB0KHJlc3BvbnNlcykgI3NvIHRoYXQgbWVsdCBjb3JyZWN0bHkgcGlja3MgdXAgdG8gYW5kIGZyb20NCiAgICByZXNwb25zZXNfbSA8LSBtZWx0KHJlc3BvbnNlc190KQ0KICAgIG5hbWVzKHJlc3BvbnNlc19tKSA8LSBjKCJmcm9tIiwidG8iLCAibnVtYmVyIikNCiAgICANCiAgICANCiAgICAjIGZvcm1hdCBhcyBuZXR3b3JrIGVkZ2VzDQogICAgZWRnZXMgPC0gcmVzcG9uc2VzX20gDQogICAgZWRnZXMkdG8gPC0gYXMuY2hhcmFjdGVyKGVkZ2VzJHRvKSANCiAgICBlZGdlcyR3aWR0aCA8LSAoZWRnZXMkbnVtYmVyICogNTApL3N1bShlZGdlcyRudW1iZXIpDQogICAgZWRnZXMkdGl0bGUgPC0gcGFzdGUoIjxwIHN0eWxlPVwiY29sb3I6YmxhY2tcIj4iLGVkZ2VzJG51bWJlciwiPC9wPiIpDQogICAgZWRnZXMgPC0gZWRnZXNbZWRnZXMkbnVtYmVyID4gMCxdDQoNCiAgICAjIHJlbmRlciBuZXR3b3JrIA0KICAgIHZpc05ldHdvcmsobm9kZXMsIGVkZ2VzKSAlPiUNCiAgICAgIHZpc1BoeXNpY3MoIHNvbHZlciA9J2ZvcmNlQXRsYXMyQmFzZWQnKQ0KICANCiAgDQogIA0KICANCn0NCg0KY3JlYXRlX25ldHdvcmtfd2hhdHNhcHAoZmlsZSA9ICJDOi9Vc2Vycy9yb2Jlci9EZXNrdG9wL2NoYXQudHh0Iiwgd29yZCA9ICJoaSIpDQoNCg0KYGBgDQoNCg0KDQojIFVzZSBmdW5jdGlvbiB0byB3cml0ZSBjbGVhbmVyIHNoaW55IGFwcCANCg0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShzaGlueSkNCmxpYnJhcnkodmlzTmV0d29yaykNCmxpYnJhcnkoc2hpbnl0aGVtZXMpDQoNCg0KDQp1aSA8LSBmbHVpZFBhZ2UodGhlbWUgPSBzaGlueXRoZW1lKCJjb3NtbyIpLA0KDQpmbHVpZFJvdygNCg0KICAgIGNvbHVtbig2LA0KICAgICAgIyByZW5kZXIgZmlyc3QgbmV0d29yaw0KICAgICAgdmlzTmV0d29ya091dHB1dCgibmV0d29ya18xIikNCiAgICAgIA0KICAgICksDQogICAgDQogICAgY29sdW1uKDYsDQogICAgICAjIHJlbmRlciBmaXJzdCBuZXR3b3JrDQogICAgICB2aXNOZXR3b3JrT3V0cHV0KCJuZXR3b3JrXzIiKQ0KICAgICAgDQogICAgKQ0KICApLA0KDQoNCmZsdWlkUm93KA0KICAgIGNvbHVtbig0LA0KICAgICAgDQogICAgICAjIGZpbGUgaW5wdXQgMQ0KICAgICAgZmlsZUlucHV0KCJmaWxlXzEiLCAiQ2hvb3NlIHR4dCBGaWxlIDEiLA0KICAgICAgICBhY2NlcHQgPSBjKA0KICAgICAgICAgICJ0ZXh0L2NzdiIsDQogICAgICAgICAgInRleHQvY29tbWEtc2VwYXJhdGVkLXZhbHVlcyx0ZXh0L3BsYWluIiwNCiAgICAgICAgICAiLmNzdiIsDQogICAgICAgICAgIi50eHQiKQ0KICAgICAgICApLA0KICAgICAgdGFncyRocigpLA0KICAgDQogICAgICANCiAgICAgICMgY3JlYXRlIHVzZXIgaW5wdXQgd29yZCBib3ggDQogICAgICB0ZXh0SW5wdXQoIndvcmRfMSIsICJXb3JkIGZvciBmaXJzdCBuZXR3b3JrIiwgdmFsdWUgPSAiaGkgIikNCg0KICAgICksIA0KICAgIGNvbHVtbig0KSwNCiAgICBjb2x1bW4oNCwNCiAgICAgICMgZmlsZSBpbnB1dCAyDQogICAgICBmaWxlSW5wdXQoImZpbGVfMiIsICJDaG9vc2UgdHh0IEZpbGUgMiIsDQogICAgICBhY2NlcHQgPSBjKA0KICAgICAgICAidGV4dC9jc3YiLA0KICAgICAgICAidGV4dC9jb21tYS1zZXBhcmF0ZWQtdmFsdWVzLHRleHQvcGxhaW4iLA0KICAgICAgICAiLmNzdiIsDQogICAgICAgICIudHh0IikpLA0KICAgICAgDQogICAgICAjIGNyZWF0ZSB1c2VyIGlucHV0IHdvcmQgYm94IA0KICAgICAgdGV4dElucHV0KCJ3b3JkXzIiLCAiV29yZCBmb3Igc2Vjb25kIG5ldHdvcmsiLCB2YWx1ZSA9ICJoaSAiKQ0KICAgICAgKQ0KICAgICkNCikNCg0KDQoNCnNlcnZlciA8LSBmdW5jdGlvbihpbnB1dCwgb3V0cHV0KSB7DQoNCiAgICAjIENyZWF0ZSBOZXR3b3JrIDENCiAgICBvdXRwdXQkbmV0d29ya18xIDwtIHJlbmRlclZpc05ldHdvcmsoew0KICAgIA0KICAgIA0KICAgICMgaW5wdXQkZmlsZTEgd2lsbCBiZSBOVUxMIGluaXRpYWxseS4gQWZ0ZXIgdGhlIHVzZXIgc2VsZWN0cw0KICAgICMgYW5kIHVwbG9hZHMgYSBmaWxlLCBpdCB3aWxsIGJlIGEgZGF0YSBmcmFtZQ0KICAgIGluRmlsZV8xIDwtIGlucHV0JGZpbGVfMQ0KDQogICAgaWYgKGlzLm51bGwoaW5GaWxlXzEpKQ0KICAgICAgcmV0dXJuKE5VTEwpDQogICAgDQogICAgY3JlYXRlX25ldHdvcmtfd2hhdHNhcHAoaW5GaWxlXzEkZGF0YXBhdGgsIGlucHV0JHdvcmRfMSkNCg0KICB9KQ0KICANCiAgICAgICMgQ3JlYXRlIE5ldHdvcmsgMg0KICAgIG91dHB1dCRuZXR3b3JrXzIgPC0gcmVuZGVyVmlzTmV0d29yayh7DQogICAgDQogICAgDQogICAgIyBpbnB1dCRmaWxlMSB3aWxsIGJlIE5VTEwgaW5pdGlhbGx5LiBBZnRlciB0aGUgdXNlciBzZWxlY3RzDQogICAgIyBhbmQgdXBsb2FkcyBhIGZpbGUsIGl0IHdpbGwgYmUgYSBkYXRhIGZyYW1lDQogICAgaW5GaWxlXzIgPC0gaW5wdXQkZmlsZV8yDQoNCiAgICBpZiAoaXMubnVsbChpbkZpbGVfMikpDQogICAgICByZXR1cm4oTlVMTCkNCiAgICANCiAgICBjcmVhdGVfbmV0d29ya193aGF0c2FwcChpbkZpbGVfMiRkYXRhcGF0aCwgaW5wdXQkd29yZF8yKQ0KDQogIH0pICANCiAgICANCiAgDQp9DQoNCnNoaW55QXBwKHVpLCBzZXJ2ZXIpDQoNCg0KDQpgYGANCg==